core_validation.cpp revision 79fc00370d55e7cbfd4052b579120e64b0a1a4be
14f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes/* Copyright (c) 2015-2017 The Khronos Group Inc.
24f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes * Copyright (c) 2015-2017 Valve Corporation
34f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes * Copyright (c) 2015-2017 LunarG, Inc.
44f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes * Copyright (C) 2015-2017 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>
2560cbbd8f316f5dfc7997bb66833a2e624f832e37Mark Lobodzinski * Author: Dave Houlton <daveh@lunarg.com>
2660cbbd8f316f5dfc7997bb66833a2e624f832e37Mark Lobodzinski * Author: Dustin Graves <dustin@lunarg.com>
2760cbbd8f316f5dfc7997bb66833a2e624f832e37Mark Lobodzinski * Author: Jeremy Hayes <jeremy@lunarg.com>
2860cbbd8f316f5dfc7997bb66833a2e624f832e37Mark Lobodzinski * Author: Jon Ashburn <jon@lunarg.com>
2960cbbd8f316f5dfc7997bb66833a2e624f832e37Mark Lobodzinski * Author: Karl Schultz <karl@lunarg.com>
3060cbbd8f316f5dfc7997bb66833a2e624f832e37Mark Lobodzinski * Author: Mark Young <marky@lunarg.com>
3160cbbd8f316f5dfc7997bb66833a2e624f832e37Mark Lobodzinski * Author: Mike Schuchardt <mikes@lunarg.com>
3260cbbd8f316f5dfc7997bb66833a2e624f832e37Mark Lobodzinski * Author: Mike Weiblen <mikew@lunarg.com>
3360cbbd8f316f5dfc7997bb66833a2e624f832e37Mark Lobodzinski * Author: Tony Barbour <tony@LunarG.com>
345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis */
355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Allow use of STL min and max functions in Windows
375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#define NOMINMAX
385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
3994c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis#include <algorithm>
4094c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis#include <assert.h>
4194c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis#include <iostream>
4294c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis#include <list>
4394c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis#include <map>
44c8bee427d7a8ed0ccec899fbf47134d582dcafbdGabríel Arthúr Pétursson#include <memory>
45b9e992386a44404152747d66817a733aa127e281Jeremy Hayes#include <mutex>
4694c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis#include <set>
4768d157d34807071526e5d78b3b3b68c5a4c6185fMark Lobodzinski#include <sstream>
485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#include <stdio.h>
495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#include <stdlib.h>
505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#include <string.h>
5194c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis#include <string>
525770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus#include <inttypes.h>
535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#include "vk_loader_platform.h"
555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#include "vk_dispatch_table_helper.h"
5668d157d34807071526e5d78b3b3b68c5a4c6185fMark Lobodzinski#include "vk_enum_string_helper.h"
575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#if defined(__GNUC__)
585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#pragma GCC diagnostic ignored "-Wwrite-strings"
595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#endif
605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#if defined(__GNUC__)
615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#pragma GCC diagnostic warning "-Wwrite-strings"
625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#endif
635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#include "core_validation.h"
64c06c9b88f5f5bcc7033ba41d5547b048fa6015a4Mark Lobodzinski#include "buffer_validation.h"
65d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes#include "shader_validation.h"
665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#include "vk_layer_table.h"
675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#include "vk_layer_data.h"
685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#include "vk_layer_extension_utils.h"
695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#include "vk_layer_utils.h"
705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#if defined __ANDROID__
725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#include <android/log.h>
735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#define LOGCONSOLE(...) ((void)__android_log_print(ANDROID_LOG_INFO, "DS", __VA_ARGS__))
745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#else
75cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#define LOGCONSOLE(...)      \
76cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    {                        \
77cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        printf(__VA_ARGS__); \
78cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        printf("\n");        \
79c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine    }
805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#endif
815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
825770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus// TODO: remove on NDK update (r15 will probably have proper STL impl)
835770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus#ifdef __ANDROID__
845770f8ad21c40b2475201e73e9368a899b6886d0Petr Krausnamespace std {
855770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
865770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraustemplate <typename T>
875770f8ad21c40b2475201e73e9368a899b6886d0Petr Krausstd::string to_string(T var) {
885770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    std::ostringstream ss;
895770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    ss << var;
905770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    return ss.str();
915770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus}
925770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus}
935770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus#endif
945770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
95d147a5463f8581604ca542aa1a44a27e512e0f60Mike Stroyan// This intentionally includes a cpp file
96d147a5463f8581604ca542aa1a44a27e512e0f60Mike Stroyan#include "vk_safe_struct.cpp"
97d147a5463f8581604ca542aa1a44a27e512e0f60Mike Stroyan
98ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbesusing mutex_t = std::mutex;
99ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbesusing lock_guard_t = std::lock_guard<mutex_t>;
100ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbesusing unique_lock_t = std::unique_lock<mutex_t>;
101ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes
102d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wunamespace core_validation {
103d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu
1045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisusing std::unordered_map;
1055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisusing std::unordered_set;
1060c55adf45a81f44300db04ec71a797d790ef103cTobin Ehlisusing std::unique_ptr;
1070c55adf45a81f44300db04ec71a797d790ef103cTobin Ehlisusing std::vector;
1080c55adf45a81f44300db04ec71a797d790ef103cTobin Ehlisusing std::string;
1090c55adf45a81f44300db04ec71a797d790ef103cTobin Ehlisusing std::stringstream;
1100c55adf45a81f44300db04ec71a797d790ef103cTobin Ehlisusing std::max;
1115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
1125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// WSI Image Objects bypass usual Image Object creation methods.  A special Memory
1135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Object value will be used to identify them internally.
1145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic const VkDeviceMemory MEMTRACKER_SWAP_CHAIN_IMAGE_KEY = (VkDeviceMemory)(-1);
115888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis// 2nd special memory handle used to flag object as unbound from memory
116888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlisstatic const VkDeviceMemory MEMORY_UNBOUND = VkDeviceMemory(~((uint64_t)(0)) - 1);
117b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis
1182e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill// A special value of (0xFFFFFFFF, 0xFFFFFFFF) indicates that the surface size will be determined
1192e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill// by the extent of a swapchain targeting the surface.
1202e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madillstatic const uint32_t kSurfaceSizeFromSwapchain = 0xFFFFFFFFu;
1212e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill
122f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbesstruct instance_layer_data {
123d3578035fec44db2380099c2f59d3e4d8e0b98d6Chris Forbes    VkInstance instance = VK_NULL_HANDLE;
124d3578035fec44db2380099c2f59d3e4d8e0b98d6Chris Forbes    debug_report_data *report_data = nullptr;
1255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    std::vector<VkDebugReportCallbackEXT> logging_callback;
1269172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes    VkLayerInstanceDispatchTable dispatch_table;
1279172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes
128219f00ffed576643641976122fa1db8e5fce5dc1Chris Forbes    CALL_STATE vkEnumeratePhysicalDevicesState = UNCALLED;
129219f00ffed576643641976122fa1db8e5fce5dc1Chris Forbes    uint32_t physical_devices_count = 0;
130b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young    CALL_STATE vkEnumeratePhysicalDeviceGroupsState = UNCALLED;
131b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young    uint32_t physical_device_groups_count = 0;
132219f00ffed576643641976122fa1db8e5fce5dc1Chris Forbes    CHECK_DISABLED disabled = {};
133219f00ffed576643641976122fa1db8e5fce5dc1Chris Forbes
134f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbes    unordered_map<VkPhysicalDevice, PHYSICAL_DEVICE_STATE> physical_device_map;
135747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    unordered_map<VkSurfaceKHR, SURFACE_STATE> surface_map;
136747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
1370cf009a4e2a5c22e4645f343c7a998f188a22015Chris Forbes    InstanceExtensions extensions;
138f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbes};
139f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbes
140f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbesstruct layer_data {
141f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbes    debug_report_data *report_data = nullptr;
1424a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkLayerDispatchTable dispatch_table;
14394c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis
144a149f1a0cb39b48b19822c8cf9ef2426cd2251dfMark Lobodzinski    DeviceExtensions extensions = {};
145cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    unordered_set<VkQueue> queues;  // All queues under given device
1465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Layer specific data
147d31a44af6da568692a73201825459689c9431867Tobin Ehlis    unordered_map<VkSampler, unique_ptr<SAMPLER_STATE>> samplerMap;
14879fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis    unordered_map<VkImageView, unique_ptr<IMAGE_VIEW_STATE>> imageViewMap;
1491facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis    unordered_map<VkImage, unique_ptr<IMAGE_STATE>> imageMap;
15039267c0c27b8f032f05a6747eb02d4508247fdc1Tobin Ehlis    unordered_map<VkBufferView, unique_ptr<BUFFER_VIEW_STATE>> bufferViewMap;
1515cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis    unordered_map<VkBuffer, unique_ptr<BUFFER_STATE>> bufferMap;
1524c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis    unordered_map<VkPipeline, PIPELINE_STATE *> pipelineMap;
1538d6a38de0389036581ada119e548180c614fe0efChris Forbes    unordered_map<VkCommandPool, COMMAND_POOL_NODE> commandPoolMap;
154a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis    unordered_map<VkDescriptorPool, DESCRIPTOR_POOL_STATE *> descriptorPoolMap;
155397d27da37095073c8b86f9ff5289d0a39ce486eTobin Ehlis    unordered_map<VkDescriptorSet, cvdescriptorset::DescriptorSet *> setMap;
1563f75ec6fa8700769a790d84e07c270579ded5468Tobin Ehlis    unordered_map<VkDescriptorSetLayout, std::shared_ptr<cvdescriptorset::DescriptorSetLayout const>> descriptorSetLayoutMap;
1575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    unordered_map<VkPipelineLayout, PIPELINE_LAYOUT_NODE> pipelineLayoutMap;
15857fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis    unordered_map<VkDeviceMemory, unique_ptr<DEVICE_MEM_INFO>> memObjMap;
1595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    unordered_map<VkFence, FENCE_NODE> fenceMap;
16036c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlis    unordered_map<VkQueue, QUEUE_STATE> queueMap;
1614710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis    unordered_map<VkEvent, EVENT_STATE> eventMap;
1625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    unordered_map<QueryObject, bool> queryToStateMap;
1635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    unordered_map<VkQueryPool, QUERY_POOL_NODE> queryPoolMap;
1645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    unordered_map<VkSemaphore, SEMAPHORE_NODE> semaphoreMap;
16572d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis    unordered_map<VkCommandBuffer, GLOBAL_CB_NODE *> commandBufferMap;
166c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis    unordered_map<VkFramebuffer, unique_ptr<FRAMEBUFFER_STATE>> frameBufferMap;
1675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    unordered_map<VkImage, vector<ImageSubresourcePair>> imageSubresourceMap;
1685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    unordered_map<ImageSubresourcePair, IMAGE_LAYOUT_NODE> imageLayoutMap;
169127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis    unordered_map<VkRenderPass, unique_ptr<RENDER_PASS_STATE>> renderPassMap;
170918c283ac4f8c604b79abd0c8b5706d2a7352a34Chris Forbes    unordered_map<VkShaderModule, unique_ptr<shader_module>> shaderModuleMap;
1716246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski    unordered_map<VkDescriptorUpdateTemplateKHR, unique_ptr<TEMPLATE_STATE>> desc_template_map;
17216a1f8f9c4af479b1873e82ff02360817fb658acChris Forbes    unordered_map<VkSwapchainKHR, std::unique_ptr<SWAPCHAIN_NODE>> swapchainMap;
17307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski
174d3578035fec44db2380099c2f59d3e4d8e0b98d6Chris Forbes    VkDevice device = VK_NULL_HANDLE;
175ec85232c4d8d9ddf7d2ae57cb8203c5ab52c1106Mark Lobodzinski    VkPhysicalDevice physical_device = VK_NULL_HANDLE;
1765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
177cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    instance_layer_data *instance_data = nullptr;  // from device to enclosing instance
17807a464bd7fec9583f346b8c4b8d43c88d2e9ffa4Chris Forbes
179f71dd305f197826a61f398bff725267a20ea1d90Chris Forbes    VkPhysicalDeviceFeatures enabled_features = {};
1805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Device specific data
181d3578035fec44db2380099c2f59d3e4d8e0b98d6Chris Forbes    PHYS_DEV_PROPERTIES_NODE phys_dev_properties = {};
182d3578035fec44db2380099c2f59d3e4d8e0b98d6Chris Forbes    VkPhysicalDeviceMemoryProperties phys_dev_mem_props = {};
183e47dbc3f3340fa177d877a67b2adb76a570027e5Mark Lobodzinski    VkPhysicalDeviceProperties phys_dev_props = {};
1845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis};
1855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
186b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis// TODO : Do we need to guard access to layer_data_map w/ lock?
187b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlisstatic unordered_map<void *, layer_data *> layer_data_map;
188f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbesstatic unordered_map<void *, instance_layer_data *> instance_layer_data_map;
189b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis
190b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Youngstatic uint32_t loader_layer_if_version = CURRENT_LOADER_LAYER_INTERFACE_VERSION;
191b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young
192e11120777bcd1543455d1de54b89292879bcd2bbChia-I Wustatic const VkLayerProperties global_layer = {
193f1ea418f193d10a8455cdf47e0eeeeb1f4d8b5bfJon Ashburn    "VK_LAYER_LUNARG_core_validation", VK_LAYER_API_VERSION, 1, "LunarG Validation Layer",
194e11120777bcd1543455d1de54b89292879bcd2bbChia-I Wu};
1955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
196cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskitemplate <class TCreateInfo>
197cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskivoid ValidateLayerOrdering(const TCreateInfo &createInfo) {
1985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    bool foundLayer = false;
1995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < createInfo.enabledLayerCount; ++i) {
200e11120777bcd1543455d1de54b89292879bcd2bbChia-I Wu        if (!strcmp(createInfo.ppEnabledLayerNames[i], global_layer.layerName)) {
2015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            foundLayer = true;
2025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
2035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // This has to be logged to console as we don't have a callback at this point.
2045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (!foundLayer && !strcmp(createInfo.ppEnabledLayerNames[0], "VK_LAYER_GOOGLE_unique_objects")) {
205bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski            LOGCONSOLE("Cannot activate layer VK_LAYER_GOOGLE_unique_objects prior to activating %s.", global_layer.layerName);
2065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
2075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
2085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
2095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// TODO : This can be much smarter, using separate locks for separate global data
211ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbesstatic mutex_t global_lock;
212593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis
21379fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis// Return IMAGE_VIEW_STATE ptr for specified imageView or else NULL
2149a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisIMAGE_VIEW_STATE *GetImageViewState(const layer_data *dev_data, VkImageView image_view) {
2152c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis    auto iv_it = dev_data->imageViewMap.find(image_view);
2162c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis    if (iv_it == dev_data->imageViewMap.end()) {
2172c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis        return nullptr;
2182c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis    }
2192c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis    return iv_it->second.get();
2202c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis}
2219a55ca3674bb3fac3fbdfca9515a16a224aa9055Tobin Ehlis// Return sampler node ptr for specified sampler or else NULL
2229a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisSAMPLER_STATE *GetSamplerState(const layer_data *dev_data, VkSampler sampler) {
2232c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis    auto sampler_it = dev_data->samplerMap.find(sampler);
2242c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis    if (sampler_it == dev_data->samplerMap.end()) {
2259a55ca3674bb3fac3fbdfca9515a16a224aa9055Tobin Ehlis        return nullptr;
2269a55ca3674bb3fac3fbdfca9515a16a224aa9055Tobin Ehlis    }
2279a55ca3674bb3fac3fbdfca9515a16a224aa9055Tobin Ehlis    return sampler_it->second.get();
2289a55ca3674bb3fac3fbdfca9515a16a224aa9055Tobin Ehlis}
2295cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis// Return image state ptr for specified image or else NULL
2309a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisIMAGE_STATE *GetImageState(const layer_data *dev_data, VkImage image) {
2316d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis    auto img_it = dev_data->imageMap.find(image);
2326d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis    if (img_it == dev_data->imageMap.end()) {
2336d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis        return nullptr;
2346d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis    }
2356d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis    return img_it->second.get();
2366d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis}
2375cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis// Return buffer state ptr for specified buffer or else NULL
2389a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisBUFFER_STATE *GetBufferState(const layer_data *dev_data, VkBuffer buffer) {
2392c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis    auto buff_it = dev_data->bufferMap.find(buffer);
2402c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis    if (buff_it == dev_data->bufferMap.end()) {
2418718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis        return nullptr;
2428718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis    }
2438718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis    return buff_it->second.get();
2448718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis}
245b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis// Return swapchain node for specified swapchain or else NULL
2469a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisSWAPCHAIN_NODE *GetSwapchainNode(const layer_data *dev_data, VkSwapchainKHR swapchain) {
24716a1f8f9c4af479b1873e82ff02360817fb658acChris Forbes    auto swp_it = dev_data->swapchainMap.find(swapchain);
24816a1f8f9c4af479b1873e82ff02360817fb658acChris Forbes    if (swp_it == dev_data->swapchainMap.end()) {
249b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis        return nullptr;
250b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis    }
2513f687bf405355f3eec6bd1bc0e8d04daba37a0f9Tobin Ehlis    return swp_it->second.get();
252b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis}
2532f2db584f5d79892bd84d0a24b8ca3499985a5c2Tobin Ehlis// Return buffer node ptr for specified buffer or else NULL
2549a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisBUFFER_VIEW_STATE *GetBufferViewState(const layer_data *dev_data, VkBufferView buffer_view) {
25551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    auto bv_it = dev_data->bufferViewMap.find(buffer_view);
25651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    if (bv_it == dev_data->bufferViewMap.end()) {
2572f2db584f5d79892bd84d0a24b8ca3499985a5c2Tobin Ehlis        return nullptr;
2582f2db584f5d79892bd84d0a24b8ca3499985a5c2Tobin Ehlis    }
2592f2db584f5d79892bd84d0a24b8ca3499985a5c2Tobin Ehlis    return bv_it->second.get();
2602f2db584f5d79892bd84d0a24b8ca3499985a5c2Tobin Ehlis}
2618718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis
2629a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisFENCE_NODE *GetFenceNode(layer_data *dev_data, VkFence fence) {
26366fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes    auto it = dev_data->fenceMap.find(fence);
26466fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes    if (it == dev_data->fenceMap.end()) {
26566fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes        return nullptr;
26666fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes    }
26766fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes    return &it->second;
26866fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes}
26966fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes
2709a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisEVENT_STATE *GetEventNode(layer_data *dev_data, VkEvent event) {
2719556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis    auto it = dev_data->eventMap.find(event);
2729556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis    if (it == dev_data->eventMap.end()) {
2739556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis        return nullptr;
2749556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis    }
2759556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis    return &it->second;
2769556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis}
2779556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis
2789a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisQUERY_POOL_NODE *GetQueryPoolNode(layer_data *dev_data, VkQueryPool query_pool) {
279ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis    auto it = dev_data->queryPoolMap.find(query_pool);
280ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis    if (it == dev_data->queryPoolMap.end()) {
281ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis        return nullptr;
282ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis    }
283ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis    return &it->second;
284ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis}
285ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis
2869a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisQUEUE_STATE *GetQueueState(layer_data *dev_data, VkQueue queue) {
28766fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes    auto it = dev_data->queueMap.find(queue);
28866fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes    if (it == dev_data->queueMap.end()) {
28966fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes        return nullptr;
29066fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes    }
29166fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes    return &it->second;
29266fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes}
29366fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes
2949a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisSEMAPHORE_NODE *GetSemaphoreNode(layer_data *dev_data, VkSemaphore semaphore) {
2955e92f3cfdca6a52a3dcefd053c41f728bd036cebChris Forbes    auto it = dev_data->semaphoreMap.find(semaphore);
2965e92f3cfdca6a52a3dcefd053c41f728bd036cebChris Forbes    if (it == dev_data->semaphoreMap.end()) {
2975e92f3cfdca6a52a3dcefd053c41f728bd036cebChris Forbes        return nullptr;
2985e92f3cfdca6a52a3dcefd053c41f728bd036cebChris Forbes    }
2995e92f3cfdca6a52a3dcefd053c41f728bd036cebChris Forbes    return &it->second;
3005e92f3cfdca6a52a3dcefd053c41f728bd036cebChris Forbes}
3015e92f3cfdca6a52a3dcefd053c41f728bd036cebChris Forbes
3029a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisCOMMAND_POOL_NODE *GetCommandPoolNode(layer_data *dev_data, VkCommandPool pool) {
3038d6a38de0389036581ada119e548180c614fe0efChris Forbes    auto it = dev_data->commandPoolMap.find(pool);
3048d6a38de0389036581ada119e548180c614fe0efChris Forbes    if (it == dev_data->commandPoolMap.end()) {
3058d6a38de0389036581ada119e548180c614fe0efChris Forbes        return nullptr;
3068d6a38de0389036581ada119e548180c614fe0efChris Forbes    }
3078d6a38de0389036581ada119e548180c614fe0efChris Forbes    return &it->second;
3088d6a38de0389036581ada119e548180c614fe0efChris Forbes}
3093bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes
3109a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisPHYSICAL_DEVICE_STATE *GetPhysicalDeviceState(instance_layer_data *instance_data, VkPhysicalDevice phys) {
311f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbes    auto it = instance_data->physical_device_map.find(phys);
312f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbes    if (it == instance_data->physical_device_map.end()) {
3133bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes        return nullptr;
3143bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes    }
3153bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes    return &it->second;
3163bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes}
3173bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes
3189a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisSURFACE_STATE *GetSurfaceState(instance_layer_data *instance_data, VkSurfaceKHR surface) {
319747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    auto it = instance_data->surface_map.find(surface);
320747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    if (it == instance_data->surface_map.end()) {
321747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes        return nullptr;
322747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    }
323747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    return &it->second;
324747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes}
325747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
326d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris ForbesDeviceExtensions const *GetEnabledExtensions(layer_data const *dev_data) {
327d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes    return &dev_data->extensions;
328d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes}
329d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes
330f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis// Return ptr to memory binding for given handle of specified type
3317a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinskistatic BINDABLE *GetObjectMemBinding(layer_data *dev_data, uint64_t handle, VulkanObjectType type) {
3325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    switch (type) {
3337a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski        case kVulkanObjectTypeImage:
3349a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            return GetImageState(dev_data, VkImage(handle));
3357a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski        case kVulkanObjectTypeBuffer:
3369a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            return GetBufferState(dev_data, VkBuffer(handle));
337cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        default:
338cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            break;
3395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
34094c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis    return nullptr;
3415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
34272d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis// prototype
3439a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisGLOBAL_CB_NODE *GetCBNode(layer_data const *, const VkCommandBuffer);
34472d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis
3455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Return ptr to info in map container containing mem, or NULL if not found
3465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis//  Calls to this function should be wrapped in mutex
3479a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisDEVICE_MEM_INFO *GetMemObjInfo(const layer_data *dev_data, const VkDeviceMemory mem) {
34857fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis    auto mem_it = dev_data->memObjMap.find(mem);
34957fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis    if (mem_it == dev_data->memObjMap.end()) {
3505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return NULL;
3515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
35257fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis    return mem_it->second.get();
3535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
3545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
35551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic void add_mem_obj_info(layer_data *dev_data, void *object, const VkDeviceMemory mem,
3565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                             const VkMemoryAllocateInfo *pAllocateInfo) {
3575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    assert(object != NULL);
3585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
35951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    dev_data->memObjMap[mem] = unique_ptr<DEVICE_MEM_INFO>(new DEVICE_MEM_INFO(object, mem, pAllocateInfo));
3605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
361dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis
362cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis// For given bound_object_handle, bound to given mem allocation, verify that the range for the bound object is valid
3637a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinskistatic bool ValidateMemoryIsValid(layer_data *dev_data, VkDeviceMemory mem, uint64_t bound_object_handle, VulkanObjectType type,
3647a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski                                  const char *functionName) {
3659a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    DEVICE_MEM_INFO *mem_info = GetMemObjInfo(dev_data, mem);
366f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis    if (mem_info) {
367f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis        if (!mem_info->bound_ranges[bound_object_handle].valid) {
368f48a83f5b5548cd46a12770c7542ff902537ad3eKarl Schultz            return log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
3699b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                           HandleToUint64(mem), __LINE__, MEMTRACK_INVALID_MEM_REGION, "MEM",
370dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis                           "%s: Cannot read invalid region of memory allocation 0x%" PRIx64 " for bound %s object 0x%" PRIx64
371dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis                           ", please fill the memory before using.",
3729b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                           functionName, HandleToUint64(mem), object_string[type], bound_object_handle);
373f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis        }
374f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis    }
375f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis    return false;
376f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis}
3771facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis// For given image_state
3781facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis//  If mem is special swapchain key, then verify that image_state valid member is true
379f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis//  Else verify that the image's bound memory range is valid
38060568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinskibool ValidateImageMemoryIsValid(layer_data *dev_data, IMAGE_STATE *image_state, const char *functionName) {
381e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis    if (image_state->binding.mem == MEMTRACKER_SWAP_CHAIN_IMAGE_KEY) {
3821facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis        if (!image_state->valid) {
383f48a83f5b5548cd46a12770c7542ff902537ad3eKarl Schultz            return log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
3849b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                           HandleToUint64(image_state->binding.mem), __LINE__, MEMTRACK_INVALID_MEM_REGION, "MEM",
385414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                           "%s: Cannot read invalid swapchain image 0x%" PRIx64 ", please fill the memory before using.",
3869b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                           functionName, HandleToUint64(image_state->image));
3875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
3885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    } else {
3899b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus        return ValidateMemoryIsValid(dev_data, image_state->binding.mem, HandleToUint64(image_state->image), kVulkanObjectTypeImage,
3909b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                     functionName);
3915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
3925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return false;
3935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
3945cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis// For given buffer_state, verify that the range it's bound to is valid
395c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinskibool ValidateBufferMemoryIsValid(layer_data *dev_data, BUFFER_STATE *buffer_state, const char *functionName) {
3969b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus    return ValidateMemoryIsValid(dev_data, buffer_state->binding.mem, HandleToUint64(buffer_state->buffer), kVulkanObjectTypeBuffer,
3979b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                 functionName);
398f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis}
399f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis// For the given memory allocation, set the range bound by the given handle object to the valid param value
400f989de4217bce0f293121d0da53dc8328276370fTobin Ehlisstatic void SetMemoryValid(layer_data *dev_data, VkDeviceMemory mem, uint64_t handle, bool valid) {
4019a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    DEVICE_MEM_INFO *mem_info = GetMemObjInfo(dev_data, mem);
402f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis    if (mem_info) {
403f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis        mem_info->bound_ranges[handle].valid = valid;
404f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis    }
405f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis}
406f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis// For given image node
4071facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis//  If mem is special swapchain key, then set entire image_state to valid param value
408f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis//  Else set the image's bound memory range to valid param value
409623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinskivoid SetImageMemoryValid(layer_data *dev_data, IMAGE_STATE *image_state, bool valid) {
410e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis    if (image_state->binding.mem == MEMTRACKER_SWAP_CHAIN_IMAGE_KEY) {
4111facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis        image_state->valid = valid;
4125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    } else {
4139b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus        SetMemoryValid(dev_data, image_state->binding.mem, HandleToUint64(image_state->image), valid);
4145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
4155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
416f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis// For given buffer node set the buffer's bound memory range to valid param value
417c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinskivoid SetBufferMemoryValid(layer_data *dev_data, BUFFER_STATE *buffer_state, bool valid) {
4189b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus    SetMemoryValid(dev_data, buffer_state->binding.mem, HandleToUint64(buffer_state->buffer), valid);
419f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis}
420ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis
42156f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis// Create binding link between given sampler and command buffer node
422d31a44af6da568692a73201825459689c9431867Tobin Ehlisvoid AddCommandBufferBindingSampler(GLOBAL_CB_NODE *cb_node, SAMPLER_STATE *sampler_state) {
423d31a44af6da568692a73201825459689c9431867Tobin Ehlis    sampler_state->cb_bindings.insert(cb_node);
4249b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus    cb_node->object_bindings.insert({HandleToUint64(sampler_state->sampler), kVulkanObjectTypeSampler});
42556f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis}
42656f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis
42756f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis// Create binding link between given image node and command buffer node
4281facd2c91911508b9fb61f54a56269841299f663Tobin Ehlisvoid AddCommandBufferBindingImage(const layer_data *dev_data, GLOBAL_CB_NODE *cb_node, IMAGE_STATE *image_state) {
429ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    // Skip validation if this image was created through WSI
430e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis    if (image_state->binding.mem != MEMTRACKER_SWAP_CHAIN_IMAGE_KEY) {
431ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        // First update CB binding in MemObj mini CB list
432d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis        for (auto mem_binding : image_state->GetBoundMemory()) {
4339a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            DEVICE_MEM_INFO *pMemInfo = GetMemObjInfo(dev_data, mem_binding);
434d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis            if (pMemInfo) {
435d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis                pMemInfo->cb_bindings.insert(cb_node);
436d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis                // Now update CBInfo's Mem reference list
437d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis                cb_node->memObjs.insert(mem_binding);
438d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis            }
439ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        }
440f940225c9e5e3e14b3f5a32d3ea360b585614600Tobin Ehlis        // Now update cb binding for image
4419b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus        cb_node->object_bindings.insert({HandleToUint64(image_state->image), kVulkanObjectTypeImage});
4421facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis        image_state->cb_bindings.insert(cb_node);
443ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    }
444ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis}
445ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis
44603ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis// Create binding link between given image view node and its image with command buffer node
44703ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlisvoid AddCommandBufferBindingImageView(const layer_data *dev_data, GLOBAL_CB_NODE *cb_node, IMAGE_VIEW_STATE *view_state) {
44803ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis    // First add bindings for imageView
44903ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis    view_state->cb_bindings.insert(cb_node);
4509b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus    cb_node->object_bindings.insert({HandleToUint64(view_state->image_view), kVulkanObjectTypeImageView});
4519a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto image_state = GetImageState(dev_data, view_state->create_info.image);
45203ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis    // Add bindings for image within imageView
4531facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis    if (image_state) {
4541facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis        AddCommandBufferBindingImage(dev_data, cb_node, image_state);
45503ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis    }
45603ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis}
45703ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis
458ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis// Create binding link between given buffer node and command buffer node
4595cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlisvoid AddCommandBufferBindingBuffer(const layer_data *dev_data, GLOBAL_CB_NODE *cb_node, BUFFER_STATE *buffer_state) {
460ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    // First update CB binding in MemObj mini CB list
4615cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis    for (auto mem_binding : buffer_state->GetBoundMemory()) {
4629a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        DEVICE_MEM_INFO *pMemInfo = GetMemObjInfo(dev_data, mem_binding);
463d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis        if (pMemInfo) {
464d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis            pMemInfo->cb_bindings.insert(cb_node);
465d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis            // Now update CBInfo's Mem reference list
466d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis            cb_node->memObjs.insert(mem_binding);
467d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis        }
468ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    }
469ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    // Now update cb binding for buffer
4709b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus    cb_node->object_bindings.insert({HandleToUint64(buffer_state->buffer), kVulkanObjectTypeBuffer});
4715cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis    buffer_state->cb_bindings.insert(cb_node);
472ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis}
473ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis
47477b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis// Create binding link between given buffer view node and its buffer with command buffer node
47577b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlisvoid AddCommandBufferBindingBufferView(const layer_data *dev_data, GLOBAL_CB_NODE *cb_node, BUFFER_VIEW_STATE *view_state) {
47677b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis    // First add bindings for bufferView
47777b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis    view_state->cb_bindings.insert(cb_node);
4789b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus    cb_node->object_bindings.insert({HandleToUint64(view_state->buffer_view), kVulkanObjectTypeBufferView});
4799a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto buffer_state = GetBufferState(dev_data, view_state->create_info.buffer);
48077b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis    // Add bindings for buffer within bufferView
4815cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis    if (buffer_state) {
4825cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis        AddCommandBufferBindingBuffer(dev_data, cb_node, buffer_state);
48377b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis    }
48477b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis}
48577b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis
486400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis// For every mem obj bound to particular CB, free bindings related to that CB
487d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlisstatic void clear_cmd_buf_and_mem_references(layer_data *dev_data, GLOBAL_CB_NODE *cb_node) {
488d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis    if (cb_node) {
489d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis        if (cb_node->memObjs.size() > 0) {
490d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis            for (auto mem : cb_node->memObjs) {
4919a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                DEVICE_MEM_INFO *pInfo = GetMemObjInfo(dev_data, mem);
4925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                if (pInfo) {
493d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis                    pInfo->cb_bindings.erase(cb_node);
4945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
4955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
496d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis            cb_node->memObjs.clear();
4975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
4985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
4995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
5005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
501f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis// Clear a single object binding from given memory object, or report error if binding is missing
5027a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinskistatic bool ClearMemoryObjectBinding(layer_data *dev_data, uint64_t handle, VulkanObjectType type, VkDeviceMemory mem) {
5039a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    DEVICE_MEM_INFO *mem_info = GetMemObjInfo(dev_data, mem);
504f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis    // This obj is bound to a memory object. Remove the reference to this object in that memory object's list
505d4cd34fd49caa759cf01cafa5fa271401b17c3b9Jeremy Hayes    if (mem_info) {
506d4cd34fd49caa759cf01cafa5fa271401b17c3b9Jeremy Hayes        mem_info->obj_bindings.erase({handle, type});
507f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis    }
508f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis    return false;
509f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis}
510f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis
511f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis// ClearMemoryObjectBindings clears the binding of objects to memory
512f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis//  For the given object it pulls the memory bindings and makes sure that the bindings
513f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis//  no longer refer to the object being cleared. This occurs when objects are destroyed.
5147a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinskibool ClearMemoryObjectBindings(layer_data *dev_data, uint64_t handle, VulkanObjectType type) {
515f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis    bool skip = false;
516f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis    BINDABLE *mem_binding = GetObjectMemBinding(dev_data, handle, type);
517f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis    if (mem_binding) {
518f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis        if (!mem_binding->sparse) {
519f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis            skip = ClearMemoryObjectBinding(dev_data, handle, type, mem_binding->binding.mem);
520cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        } else {  // Sparse, clear all bindings
521bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski            for (auto &sparse_mem_binding : mem_binding->sparse_bindings) {
522f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis                skip |= ClearMemoryObjectBinding(dev_data, handle, type, sparse_mem_binding.mem);
5235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
5245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
5255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
526f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis    return skip;
5275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
5285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
529888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis// For given mem object, verify that it is not null or UNBOUND, if it is, report error. Return skip value.
530888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlisbool VerifyBoundMemoryIsValid(const layer_data *dev_data, VkDeviceMemory mem, uint64_t handle, const char *api_name,
53135ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis                              const char *type_name, UNIQUE_VALIDATION_ERROR_CODE error_code) {
532888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis    bool result = false;
533888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis    if (VK_NULL_HANDLE == mem) {
534888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis        result = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, handle,
535cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                         __LINE__, error_code, "MEM", "%s: Vk%s object 0x%" PRIxLEAST64
536cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                                                      " used with no memory bound. Memory should be bound by calling "
537cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                                                      "vkBind%sMemory(). %s",
53835ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis                         api_name, type_name, handle, type_name, validation_error_map[error_code]);
539888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis    } else if (MEMORY_UNBOUND == mem) {
540888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis        result = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, handle,
541cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                         __LINE__, error_code, "MEM", "%s: Vk%s object 0x%" PRIxLEAST64
542cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                                                      " used with no memory bound and previously bound memory was freed. "
543cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                                                      "Memory must not be freed prior to this operation. %s",
54435ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis                         api_name, type_name, handle, validation_error_map[error_code]);
545888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis    }
546888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis    return result;
547888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis}
548888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis
549b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski// Check to see if memory was ever bound to this image
55035ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlisbool ValidateMemoryIsBoundToImage(const layer_data *dev_data, const IMAGE_STATE *image_state, const char *api_name,
55135ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis                                  UNIQUE_VALIDATION_ERROR_CODE error_code) {
552b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski    bool result = false;
5531facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis    if (0 == (static_cast<uint32_t>(image_state->createInfo.flags) & VK_IMAGE_CREATE_SPARSE_BINDING_BIT)) {
5549b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus        result = VerifyBoundMemoryIsValid(dev_data, image_state->binding.mem, HandleToUint64(image_state->image), api_name, "Image",
5559b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                          error_code);
556b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski    }
557b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski    return result;
558b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski}
559b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski
560b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski// Check to see if memory was bound to this buffer
56135ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlisbool ValidateMemoryIsBoundToBuffer(const layer_data *dev_data, const BUFFER_STATE *buffer_state, const char *api_name,
56235ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis                                   UNIQUE_VALIDATION_ERROR_CODE error_code) {
563b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski    bool result = false;
5645cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis    if (0 == (static_cast<uint32_t>(buffer_state->createInfo.flags) & VK_BUFFER_CREATE_SPARSE_BINDING_BIT)) {
5659b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus        result = VerifyBoundMemoryIsValid(dev_data, buffer_state->binding.mem, HandleToUint64(buffer_state->buffer), api_name,
5669b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                          "Buffer", error_code);
567b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski    }
568b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski    return result;
569b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski}
570b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski
5713a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// SetMemBinding is used to establish immutable, non-sparse binding between a single image/buffer object and memory object.
5723a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// Corresponding valid usage checks are in ValidateSetMemBinding().
5737a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinskistatic void SetMemBinding(layer_data *dev_data, VkDeviceMemory mem, uint64_t handle, VulkanObjectType type, const char *apiName) {
574c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton    if (mem != VK_NULL_HANDLE) {
575c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton        BINDABLE *mem_binding = GetObjectMemBinding(dev_data, handle, type);
576c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton        assert(mem_binding);
577c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton        DEVICE_MEM_INFO *mem_info = GetMemObjInfo(dev_data, mem);
578c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton        if (mem_info) {
579c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton            mem_info->obj_bindings.insert({handle, type});
580c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton            // For image objects, make sure default memory state is correctly set
581c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton            // TODO : What's the best/correct way to handle this?
5827a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski            if (kVulkanObjectTypeImage == type) {
583c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton                auto const image_state = GetImageState(dev_data, VkImage(handle));
584c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton                if (image_state) {
585c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton                    VkImageCreateInfo ici = image_state->createInfo;
586c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton                    if (ici.usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) {
587c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton                        // TODO::  More memory state transition stuff.
588c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton                    }
589c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton                }
590c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton            }
591c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton            mem_binding->binding.mem = mem;
592c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton        }
593c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton    }
594c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton}
5953a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton
5963a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// Valid usage checks for a call to SetMemBinding().
5973a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// For NULL mem case, output warning
5983a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// Make sure given object is in global object map
5993a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton//  IF a previous binding existed, output validation error
6003a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton//  Otherwise, add reference from objectInfo to memoryInfo
6013a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton//  Add reference off of objInfo
6023a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// TODO: We may need to refactor or pass in multiple valid usage statements to handle multiple valid usage conditions.
6037a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinskistatic bool ValidateSetMemBinding(layer_data *dev_data, VkDeviceMemory mem, uint64_t handle, VulkanObjectType type,
604c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton                                  const char *apiName) {
6053251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
606f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis    // It's an error to bind an object to NULL memory
607d3876b4ff7c293a14f73fe3622513d1fa91bf2d0Jeremy Hayes    if (mem != VK_NULL_HANDLE) {
608f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis        BINDABLE *mem_binding = GetObjectMemBinding(dev_data, handle, type);
609888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis        assert(mem_binding);
61010ffe2d353eaff714ed92a2835af77d8b5042d31Cort        if (mem_binding->sparse) {
611315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis            UNIQUE_VALIDATION_ERROR_CODE error_code = VALIDATION_ERROR_1740082a;
61210ffe2d353eaff714ed92a2835af77d8b5042d31Cort            const char *handle_type = "IMAGE";
61374300755ed9ec780d6073af71e47f201217008d6Cort Stratton            if (strcmp(apiName, "vkBindBufferMemory()") == 0) {
614315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                error_code = VALIDATION_ERROR_1700080c;
61510ffe2d353eaff714ed92a2835af77d8b5042d31Cort                handle_type = "BUFFER";
61610ffe2d353eaff714ed92a2835af77d8b5042d31Cort            } else {
61774300755ed9ec780d6073af71e47f201217008d6Cort Stratton                assert(strcmp(apiName, "vkBindImageMemory()") == 0);
61810ffe2d353eaff714ed92a2835af77d8b5042d31Cort            }
6193251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
6209b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(mem), __LINE__, error_code, "MEM",
6213251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "In %s, attempting to bind memory (0x%" PRIxLEAST64 ") to object (0x%" PRIxLEAST64
6223251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            ") which was created with sparse memory flags (VK_%s_CREATE_SPARSE_*_BIT). %s",
6239b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            apiName, HandleToUint64(mem), handle, handle_type, validation_error_map[error_code]);
62410ffe2d353eaff714ed92a2835af77d8b5042d31Cort        }
6259a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        DEVICE_MEM_INFO *mem_info = GetMemObjInfo(dev_data, mem);
626888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis        if (mem_info) {
6279a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            DEVICE_MEM_INFO *prev_binding = GetMemObjInfo(dev_data, mem_binding->binding.mem);
628888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis            if (prev_binding) {
629315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                UNIQUE_VALIDATION_ERROR_CODE error_code = VALIDATION_ERROR_17400828;
63074300755ed9ec780d6073af71e47f201217008d6Cort Stratton                if (strcmp(apiName, "vkBindBufferMemory()") == 0) {
631315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                    error_code = VALIDATION_ERROR_1700080a;
63298c2a17e1a549df84f4239f619bc0955f632cb43Cort                } else {
63374300755ed9ec780d6073af71e47f201217008d6Cort Stratton                    assert(strcmp(apiName, "vkBindImageMemory()") == 0);
63498c2a17e1a549df84f4239f619bc0955f632cb43Cort                }
6353251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
6369b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                HandleToUint64(mem), __LINE__, error_code, "MEM",
6373251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "In %s, attempting to bind memory (0x%" PRIxLEAST64 ") to object (0x%" PRIxLEAST64
6383251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                ") which has already been bound to mem object 0x%" PRIxLEAST64 ". %s",
6399b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                apiName, HandleToUint64(mem), handle, HandleToUint64(prev_binding->mem),
6403251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                validation_error_map[error_code]);
641f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis            } else if (mem_binding->binding.mem == MEMORY_UNBOUND) {
6423251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
6439b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                HandleToUint64(mem), __LINE__, MEMTRACK_REBIND_OBJECT, "MEM",
6443251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "In %s, attempting to bind memory (0x%" PRIxLEAST64 ") to object (0x%" PRIxLEAST64
6453251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                ") which was previous bound to memory that has since been freed. Memory bindings are immutable in "
6463251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "Vulkan so this attempt to bind to new memory is not allowed.",
6479b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                apiName, HandleToUint64(mem), handle);
6485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
6495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
6505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
6513251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
6525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
6535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
6545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// For NULL mem case, clear any previous binding Else...
6555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Make sure given object is in its object map
6565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis//  IF a previous binding existed, update binding
6575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis//  Add reference from objectInfo to memoryInfo
6585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis//  Add reference off of object's binding info
6590a1ce3dfd81c9f4efbe46f5ba5ddaea70bc4aa61Chris Forbes// Return VK_TRUE if addition is successful, VK_FALSE otherwise
660ece0e981ee4a5ad2572d146a89fc64d699d79f36Chris Forbesstatic bool SetSparseMemBinding(layer_data *dev_data, MEM_BINDING binding, uint64_t handle, VulkanObjectType type) {
6613251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = VK_FALSE;
6625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Handle NULL case separately, just clear previous binding & decrement reference
663f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis    if (binding.mem == VK_NULL_HANDLE) {
664f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis        // TODO : This should cause the range of the resource to be unbound according to spec
6655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    } else {
666f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis        BINDABLE *mem_binding = GetObjectMemBinding(dev_data, handle, type);
667f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis        assert(mem_binding);
668f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis        assert(mem_binding->sparse);
6699a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        DEVICE_MEM_INFO *mem_info = GetMemObjInfo(dev_data, binding.mem);
670f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis        if (mem_info) {
671f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis            mem_info->obj_bindings.insert({handle, type});
6722e415b757c1e43fda35311aad026af8d5c96681cTobin Ehlis            // Need to set mem binding for this object
673f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis            mem_binding->sparse_bindings.insert(binding);
6745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
6755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
6763251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
677caf05e0db4959ae196ab34b024f352d9c0326870Tobin Ehlis}
678caf05e0db4959ae196ab34b024f352d9c0326870Tobin Ehlis
6795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Check object status for selected flag state
68051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool validate_status(layer_data *dev_data, GLOBAL_CB_NODE *pNode, CBStatusFlags status_mask, VkFlags msg_flags,
6814f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes                            const char *fail_msg, UNIQUE_VALIDATION_ERROR_CODE const msg_code) {
6823d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis    if (!(pNode->status & status_mask)) {
6834f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes        char const *const message = validation_error_map[msg_code];
68451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis        return log_msg(dev_data->report_data, msg_flags, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
6859b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                       HandleToUint64(pNode->commandBuffer), __LINE__, msg_code, "DS", "command buffer object 0x%p: %s. %s.",
6869b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                       pNode->commandBuffer, fail_msg, message);
6875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
688e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    return false;
6895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
6905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
6915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Retrieve pipeline node ptr for given pipeline object
69251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic PIPELINE_STATE *getPipelineState(layer_data const *dev_data, VkPipeline pipeline) {
69351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    auto it = dev_data->pipelineMap.find(pipeline);
69451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    if (it == dev_data->pipelineMap.end()) {
695ea8349eeee76ae2859c10870fd8bd9e60309eb28Chris Forbes        return nullptr;
6965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
697ea8349eeee76ae2859c10870fd8bd9e60309eb28Chris Forbes    return it->second;
6985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
6995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
7009a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisRENDER_PASS_STATE *GetRenderPassState(layer_data const *dev_data, VkRenderPass renderpass) {
70151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    auto it = dev_data->renderPassMap.find(renderpass);
70251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    if (it == dev_data->renderPassMap.end()) {
70316387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes        return nullptr;
70416387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes    }
705fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes    return it->second.get();
70616387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes}
70716387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes
7089a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisFRAMEBUFFER_STATE *GetFramebufferState(const layer_data *dev_data, VkFramebuffer framebuffer) {
70951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    auto it = dev_data->frameBufferMap.find(framebuffer);
71051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    if (it == dev_data->frameBufferMap.end()) {
711f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes        return nullptr;
712f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes    }
71304861caca7eb93a5241b164e8480bb93c826902cTobin Ehlis    return it->second.get();
714f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes}
715f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes
7163f75ec6fa8700769a790d84e07c270579ded5468Tobin Ehlisstd::shared_ptr<cvdescriptorset::DescriptorSetLayout const> const GetDescriptorSetLayout(layer_data const *dev_data,
7173f75ec6fa8700769a790d84e07c270579ded5468Tobin Ehlis                                                                                         VkDescriptorSetLayout dsLayout) {
71851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    auto it = dev_data->descriptorSetLayoutMap.find(dsLayout);
71951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    if (it == dev_data->descriptorSetLayoutMap.end()) {
72011f1fde2721c198a619e4a22fff60eef9a16fae8Chris Forbes        return nullptr;
72111f1fde2721c198a619e4a22fff60eef9a16fae8Chris Forbes    }
722d34b2c191243c1646f1ccc2378262383e9ec1348Tobin Ehlis    return it->second;
72311f1fde2721c198a619e4a22fff60eef9a16fae8Chris Forbes}
72411f1fde2721c198a619e4a22fff60eef9a16fae8Chris Forbes
72551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic PIPELINE_LAYOUT_NODE const *getPipelineLayout(layer_data const *dev_data, VkPipelineLayout pipeLayout) {
72651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    auto it = dev_data->pipelineLayoutMap.find(pipeLayout);
72751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    if (it == dev_data->pipelineLayoutMap.end()) {
7284a45a42023b281f55953222c1a6c3e80f50e5f2aChris Forbes        return nullptr;
7294a45a42023b281f55953222c1a6c3e80f50e5f2aChris Forbes    }
7304a45a42023b281f55953222c1a6c3e80f50e5f2aChris Forbes    return &it->second;
7314a45a42023b281f55953222c1a6c3e80f50e5f2aChris Forbes}
7324a45a42023b281f55953222c1a6c3e80f50e5f2aChris Forbes
733d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbesshader_module const *GetShaderModuleState(layer_data const *dev_data, VkShaderModule module) {
734d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes    auto it = dev_data->shaderModuleMap.find(module);
735d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes    if (it == dev_data->shaderModuleMap.end()) {
736d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes        return nullptr;
737d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes    }
738d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes    return it->second.get();
739d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes}
740d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes
741e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves// Return true if for a given PSO, the given state enum is dynamic, else return false
7424c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlisstatic bool isDynamic(const PIPELINE_STATE *pPipeline, const VkDynamicState state) {
7435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pPipeline && pPipeline->graphicsPipelineCI.pDynamicState) {
7445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t i = 0; i < pPipeline->graphicsPipelineCI.pDynamicState->dynamicStateCount; i++) {
745cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            if (state == pPipeline->graphicsPipelineCI.pDynamicState->pDynamicStates[i]) return true;
7465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
7475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
748e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    return false;
7495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
7505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
7515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Validate state stored as flags at time of draw call
7524f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayesstatic bool validate_draw_state_flags(layer_data *dev_data, GLOBAL_CB_NODE *pCB, const PIPELINE_STATE *pPipe, bool indexed,
7534f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes                                      UNIQUE_VALIDATION_ERROR_CODE const msg_code) {
7549c4006684a13db43f0dbc8d0015a9ef34872ca09Chris Forbes    bool result = false;
755ca546210846c65808717f8875deae39bd227c240Tobin Ehlis    if (pPipe->graphicsPipelineCI.pInputAssemblyState &&
756ca546210846c65808717f8875deae39bd227c240Tobin Ehlis        ((pPipe->graphicsPipelineCI.pInputAssemblyState->topology == VK_PRIMITIVE_TOPOLOGY_LINE_LIST) ||
757ca546210846c65808717f8875deae39bd227c240Tobin Ehlis         (pPipe->graphicsPipelineCI.pInputAssemblyState->topology == VK_PRIMITIVE_TOPOLOGY_LINE_STRIP))) {
7583d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis        result |= validate_status(dev_data, pCB, CBSTATUS_LINE_WIDTH_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT,
7594f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes                                  "Dynamic line width state not set for this command buffer", msg_code);
7603d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis    }
76145824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves    if (pPipe->graphicsPipelineCI.pRasterizationState &&
76245824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves        (pPipe->graphicsPipelineCI.pRasterizationState->depthBiasEnable == VK_TRUE)) {
7633d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis        result |= validate_status(dev_data, pCB, CBSTATUS_DEPTH_BIAS_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT,
7644f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes                                  "Dynamic depth bias state not set for this command buffer", msg_code);
7653d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis    }
7663d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis    if (pPipe->blendConstantsEnabled) {
7673d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis        result |= validate_status(dev_data, pCB, CBSTATUS_BLEND_CONSTANTS_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT,
7684f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes                                  "Dynamic blend constants state not set for this command buffer", msg_code);
7693d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis    }
77045824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves    if (pPipe->graphicsPipelineCI.pDepthStencilState &&
77145824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves        (pPipe->graphicsPipelineCI.pDepthStencilState->depthBoundsTestEnable == VK_TRUE)) {
7723d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis        result |= validate_status(dev_data, pCB, CBSTATUS_DEPTH_BOUNDS_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT,
7734f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes                                  "Dynamic depth bounds state not set for this command buffer", msg_code);
7743d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis    }
77545824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves    if (pPipe->graphicsPipelineCI.pDepthStencilState &&
77645824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves        (pPipe->graphicsPipelineCI.pDepthStencilState->stencilTestEnable == VK_TRUE)) {
7773d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis        result |= validate_status(dev_data, pCB, CBSTATUS_STENCIL_READ_MASK_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT,
7784f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes                                  "Dynamic stencil read mask state not set for this command buffer", msg_code);
7793d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis        result |= validate_status(dev_data, pCB, CBSTATUS_STENCIL_WRITE_MASK_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT,
7804f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes                                  "Dynamic stencil write mask state not set for this command buffer", msg_code);
7813d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis        result |= validate_status(dev_data, pCB, CBSTATUS_STENCIL_REFERENCE_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT,
7824f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes                                  "Dynamic stencil reference state not set for this command buffer", msg_code);
7833d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis    }
7841c130ea631a82716dc7334de17767536525f2292Tobin Ehlis    if (indexed) {
7853d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis        result |= validate_status(dev_data, pCB, CBSTATUS_INDEX_BUFFER_BOUND, VK_DEBUG_REPORT_ERROR_BIT_EXT,
7864f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes                                  "Index buffer object not bound to this command buffer when Indexed Draw attempted", msg_code);
7873d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis    }
7884f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes
7895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
7905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
7915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
7925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Verify attachment reference compatibility according to spec
7935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis//  If one array is larger, treat missing elements of shorter array as VK_ATTACHMENT_UNUSED & other array much match this
7945ca3c071afc98f9144f489b74aa3affaa93633b0Mark Lobodzinski//  If both AttachmentReference arrays have requested index, check their corresponding AttachmentDescriptions
7955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis//   to make sure that format and samples counts match.
7965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis//  If not, they are not compatible.
7975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic bool attachment_references_compatible(const uint32_t index, const VkAttachmentReference *pPrimary,
7985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                             const uint32_t primaryCount, const VkAttachmentDescription *pPrimaryAttachments,
7995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                             const VkAttachmentReference *pSecondary, const uint32_t secondaryCount,
8005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                             const VkAttachmentDescription *pSecondaryAttachments) {
801e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis    // Check potential NULL cases first to avoid nullptr issues later
802e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis    if (pPrimary == nullptr) {
803e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis        if (pSecondary == nullptr) {
804e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis            return true;
805e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis        }
806e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis        return false;
807e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis    } else if (pSecondary == nullptr) {
808e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis        return false;
809e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis    }
810cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (index >= primaryCount) {  // Check secondary as if primary is VK_ATTACHMENT_UNUSED
811cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        if (VK_ATTACHMENT_UNUSED == pSecondary[index].attachment) return true;
812cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    } else if (index >= secondaryCount) {  // Check primary as if secondary is VK_ATTACHMENT_UNUSED
813cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        if (VK_ATTACHMENT_UNUSED == pPrimary[index].attachment) return true;
814cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    } else {  // Format and sample count must match
8155ca3c071afc98f9144f489b74aa3affaa93633b0Mark Lobodzinski        if ((pPrimary[index].attachment == VK_ATTACHMENT_UNUSED) && (pSecondary[index].attachment == VK_ATTACHMENT_UNUSED)) {
8165ca3c071afc98f9144f489b74aa3affaa93633b0Mark Lobodzinski            return true;
8175ca3c071afc98f9144f489b74aa3affaa93633b0Mark Lobodzinski        } else if ((pPrimary[index].attachment == VK_ATTACHMENT_UNUSED) || (pSecondary[index].attachment == VK_ATTACHMENT_UNUSED)) {
8185ca3c071afc98f9144f489b74aa3affaa93633b0Mark Lobodzinski            return false;
8195ca3c071afc98f9144f489b74aa3affaa93633b0Mark Lobodzinski        }
8205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if ((pPrimaryAttachments[pPrimary[index].attachment].format ==
8215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis             pSecondaryAttachments[pSecondary[index].attachment].format) &&
8225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            (pPrimaryAttachments[pPrimary[index].attachment].samples ==
8235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis             pSecondaryAttachments[pSecondary[index].attachment].samples))
8245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            return true;
8255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
8265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Format and sample counts didn't match
8275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return false;
8285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
829a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis// TODO : Scrub verify_renderpass_compatibility() and validateRenderPassCompatibility() and unify them and/or share code
830266231a5421564c314f6b5d5bd3fed26fd389484Chris Forbes// For given primary RenderPass object and secondary RenderPassCreateInfo, verify that they're compatible
83151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool verify_renderpass_compatibility(const layer_data *dev_data, const VkRenderPassCreateInfo *primaryRPCI,
8328da1edac0fbed13831b2f458f27c51e64d6210ffTobin Ehlis                                            const VkRenderPassCreateInfo *secondaryRPCI, string &errorMsg) {
8335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (primaryRPCI->subpassCount != secondaryRPCI->subpassCount) {
834c07fa78efa7d4edfaa4ffbb0c2046ee8154b27beChris Forbes        stringstream errorStr;
8355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        errorStr << "RenderPass for primary cmdBuffer has " << primaryRPCI->subpassCount
8365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                 << " subpasses but renderPass for secondary cmdBuffer has " << secondaryRPCI->subpassCount << " subpasses.";
8375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        errorMsg = errorStr.str();
8385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return false;
8395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
8405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    uint32_t spIndex = 0;
8415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (spIndex = 0; spIndex < primaryRPCI->subpassCount; ++spIndex) {
8425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // For each subpass, verify that corresponding color, input, resolve & depth/stencil attachment references are compatible
8435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        uint32_t primaryColorCount = primaryRPCI->pSubpasses[spIndex].colorAttachmentCount;
8445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        uint32_t secondaryColorCount = secondaryRPCI->pSubpasses[spIndex].colorAttachmentCount;
8455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        uint32_t colorMax = std::max(primaryColorCount, secondaryColorCount);
8465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t cIdx = 0; cIdx < colorMax; ++cIdx) {
8475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (!attachment_references_compatible(cIdx, primaryRPCI->pSubpasses[spIndex].pColorAttachments, primaryColorCount,
8485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                                  primaryRPCI->pAttachments, secondaryRPCI->pSubpasses[spIndex].pColorAttachments,
8495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                                  secondaryColorCount, secondaryRPCI->pAttachments)) {
850c07fa78efa7d4edfaa4ffbb0c2046ee8154b27beChris Forbes                stringstream errorStr;
8515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                errorStr << "color attachments at index " << cIdx << " of subpass index " << spIndex << " are not compatible.";
8525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                errorMsg = errorStr.str();
8535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                return false;
8545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            } else if (!attachment_references_compatible(cIdx, primaryRPCI->pSubpasses[spIndex].pResolveAttachments,
8555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                                         primaryColorCount, primaryRPCI->pAttachments,
8565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                                         secondaryRPCI->pSubpasses[spIndex].pResolveAttachments,
8575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                                         secondaryColorCount, secondaryRPCI->pAttachments)) {
858c07fa78efa7d4edfaa4ffbb0c2046ee8154b27beChris Forbes                stringstream errorStr;
8595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                errorStr << "resolve attachments at index " << cIdx << " of subpass index " << spIndex << " are not compatible.";
8605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                errorMsg = errorStr.str();
8615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                return false;
8625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
8635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
864fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes
865bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        if (!attachment_references_compatible(0, primaryRPCI->pSubpasses[spIndex].pDepthStencilAttachment, 1,
866bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                              primaryRPCI->pAttachments, secondaryRPCI->pSubpasses[spIndex].pDepthStencilAttachment,
867fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes                                              1, secondaryRPCI->pAttachments)) {
868c07fa78efa7d4edfaa4ffbb0c2046ee8154b27beChris Forbes            stringstream errorStr;
869fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes            errorStr << "depth/stencil attachments of subpass index " << spIndex << " are not compatible.";
870fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes            errorMsg = errorStr.str();
871fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes            return false;
872fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes        }
873fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes
8745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        uint32_t primaryInputCount = primaryRPCI->pSubpasses[spIndex].inputAttachmentCount;
8755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        uint32_t secondaryInputCount = secondaryRPCI->pSubpasses[spIndex].inputAttachmentCount;
8765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        uint32_t inputMax = std::max(primaryInputCount, secondaryInputCount);
8775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t i = 0; i < inputMax; ++i) {
8781e49a9dd0518c3cd335dd040218aa9c25d7cb600Tobin Ehlis            if (!attachment_references_compatible(i, primaryRPCI->pSubpasses[spIndex].pInputAttachments, primaryInputCount,
8795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                                  primaryRPCI->pAttachments, secondaryRPCI->pSubpasses[spIndex].pInputAttachments,
8801e49a9dd0518c3cd335dd040218aa9c25d7cb600Tobin Ehlis                                                  secondaryInputCount, secondaryRPCI->pAttachments)) {
881c07fa78efa7d4edfaa4ffbb0c2046ee8154b27beChris Forbes                stringstream errorStr;
8825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                errorStr << "input attachments at index " << i << " of subpass index " << spIndex << " are not compatible.";
8835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                errorMsg = errorStr.str();
8845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                return false;
8855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
8865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
8875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
8885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return true;
8895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
8905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
8915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Return Set node ptr for specified set or else NULL
8929a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehliscvdescriptorset::DescriptorSet *GetSetNode(const layer_data *dev_data, VkDescriptorSet set) {
89351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    auto set_it = dev_data->setMap.find(set);
89451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    if (set_it == dev_data->setMap.end()) {
8955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return NULL;
8965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
897104ab082916e41467ef60baaab7a5a8b2e02c59cTobin Ehlis    return set_it->second;
8985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
8995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
900eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young// For given pipeline, return number of MSAA samples, or one if MSAA disabled
9014c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlisstatic VkSampleCountFlagBits getNumSamples(PIPELINE_STATE const *pipe) {
902ea8349eeee76ae2859c10870fd8bd9e60309eb28Chris Forbes    if (pipe->graphicsPipelineCI.pMultisampleState != NULL &&
903ea8349eeee76ae2859c10870fd8bd9e60309eb28Chris Forbes        VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO == pipe->graphicsPipelineCI.pMultisampleState->sType) {
904eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young        return pipe->graphicsPipelineCI.pMultisampleState->rasterizationSamples;
905eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young    }
906eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young    return VK_SAMPLE_COUNT_1_BIT;
907eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young}
908eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young
909bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic void list_bits(std::ostream &s, uint32_t bits) {
910b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes    for (int i = 0; i < 32 && bits; i++) {
911b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes        if (bits & (1 << i)) {
912b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes            s << i;
913b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes            bits &= ~(1 << i);
914b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes            if (bits) {
915b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes                s << ",";
916b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes            }
917b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes        }
918b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes    }
919b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes}
920b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes
921eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young// Validate draw-time state related to the PSO
92251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool ValidatePipelineDrawtimeState(layer_data const *dev_data, LAST_BOUND_STATE const &state, const GLOBAL_CB_NODE *pCB,
9234c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis                                          PIPELINE_STATE const *pPipeline) {
9243251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
92529d196e071b2dc1db47702085469396f2b956820Chris Forbes
926d79335137b414d5f89284a9ab3e014beb4ada3ebMike Weiblen    // Verify vertex binding
92729d196e071b2dc1db47702085469396f2b956820Chris Forbes    if (pPipeline->vertexBindingDescriptions.size() > 0) {
92829d196e071b2dc1db47702085469396f2b956820Chris Forbes        for (size_t i = 0; i < pPipeline->vertexBindingDescriptions.size(); i++) {
929312129ec52e6249aa453e27e6be17a8dab1e98b8Tobin Ehlis            auto vertex_binding = pPipeline->vertexBindingDescriptions[i].binding;
930312129ec52e6249aa453e27e6be17a8dab1e98b8Tobin Ehlis            if ((pCB->currentDrawData.buffers.size() < (vertex_binding + 1)) ||
931312129ec52e6249aa453e27e6be17a8dab1e98b8Tobin Ehlis                (pCB->currentDrawData.buffers[vertex_binding] == VK_NULL_HANDLE)) {
9323251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |=
933df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
9349b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(pCB->commandBuffer), __LINE__, DRAWSTATE_VTX_INDEX_OUT_OF_BOUNDS, "DS",
935cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                            "The Pipeline State Object (0x%" PRIxLEAST64
936cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                            ") expects that this Command Buffer's vertex binding Index %u "
937cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                            "should be set via vkCmdBindVertexBuffers. This is because VkVertexInputBindingDescription struct "
938cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                            "at index " PRINTF_SIZE_T_SPECIFIER " of pVertexBindingDescriptions has a binding value of %u.",
9399b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(state.pipeline_state->pipeline), vertex_binding, i, vertex_binding);
94029d196e071b2dc1db47702085469396f2b956820Chris Forbes            }
94129d196e071b2dc1db47702085469396f2b956820Chris Forbes        }
94229d196e071b2dc1db47702085469396f2b956820Chris Forbes    } else {
94358b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis        if (!pCB->currentDrawData.buffers.empty() && !pCB->vertex_buffer_used) {
9443251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT,
9459b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, HandleToUint64(pCB->commandBuffer), __LINE__,
9469b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            DRAWSTATE_VTX_INDEX_OUT_OF_BOUNDS, "DS",
9473251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "Vertex buffers are bound to command buffer (0x%p"
9483251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            ") but no vertex buffers are attached to this Pipeline State Object (0x%" PRIxLEAST64 ").",
9499b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            pCB->commandBuffer, HandleToUint64(state.pipeline_state->pipeline));
95029d196e071b2dc1db47702085469396f2b956820Chris Forbes        }
95129d196e071b2dc1db47702085469396f2b956820Chris Forbes    }
95229d196e071b2dc1db47702085469396f2b956820Chris Forbes    // If Viewport or scissors are dynamic, verify that dynamic count matches PSO count.
95329d196e071b2dc1db47702085469396f2b956820Chris Forbes    // Skip check if rasterization is disabled or there is no viewport.
95429d196e071b2dc1db47702085469396f2b956820Chris Forbes    if ((!pPipeline->graphicsPipelineCI.pRasterizationState ||
95529d196e071b2dc1db47702085469396f2b956820Chris Forbes         (pPipeline->graphicsPipelineCI.pRasterizationState->rasterizerDiscardEnable == VK_FALSE)) &&
95629d196e071b2dc1db47702085469396f2b956820Chris Forbes        pPipeline->graphicsPipelineCI.pViewportState) {
95729d196e071b2dc1db47702085469396f2b956820Chris Forbes        bool dynViewport = isDynamic(pPipeline, VK_DYNAMIC_STATE_VIEWPORT);
95829d196e071b2dc1db47702085469396f2b956820Chris Forbes        bool dynScissor = isDynamic(pPipeline, VK_DYNAMIC_STATE_SCISSOR);
959b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes
96029d196e071b2dc1db47702085469396f2b956820Chris Forbes        if (dynViewport) {
961b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes            auto requiredViewportsMask = (1 << pPipeline->graphicsPipelineCI.pViewportState->viewportCount) - 1;
962b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes            auto missingViewportMask = ~pCB->viewportMask & requiredViewportsMask;
963b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes            if (missingViewportMask) {
964b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes                std::stringstream ss;
965b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes                ss << "Dynamic viewport(s) ";
966b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes                list_bits(ss, missingViewportMask);
967d79335137b414d5f89284a9ab3e014beb4ada3ebMike Weiblen                ss << " are used by pipeline state object, but were not provided via calls to vkCmdSetViewport().";
9683251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
9693251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                __LINE__, DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS", "%s", ss.str().c_str());
97029d196e071b2dc1db47702085469396f2b956820Chris Forbes            }
97129d196e071b2dc1db47702085469396f2b956820Chris Forbes        }
972b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes
97329d196e071b2dc1db47702085469396f2b956820Chris Forbes        if (dynScissor) {
974b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes            auto requiredScissorMask = (1 << pPipeline->graphicsPipelineCI.pViewportState->scissorCount) - 1;
975b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes            auto missingScissorMask = ~pCB->scissorMask & requiredScissorMask;
976b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes            if (missingScissorMask) {
977b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes                std::stringstream ss;
978b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes                ss << "Dynamic scissor(s) ";
979b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes                list_bits(ss, missingScissorMask);
980d79335137b414d5f89284a9ab3e014beb4ada3ebMike Weiblen                ss << " are used by pipeline state object, but were not provided via calls to vkCmdSetScissor().";
9813251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
9823251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                __LINE__, DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS", "%s", ss.str().c_str());
98329d196e071b2dc1db47702085469396f2b956820Chris Forbes            }
98429d196e071b2dc1db47702085469396f2b956820Chris Forbes        }
98529d196e071b2dc1db47702085469396f2b956820Chris Forbes    }
98629d196e071b2dc1db47702085469396f2b956820Chris Forbes
98729d196e071b2dc1db47702085469396f2b956820Chris Forbes    // Verify that any MSAA request in PSO matches sample# in bound FB
98829d196e071b2dc1db47702085469396f2b956820Chris Forbes    // Skip the check if rasterization is disabled.
98929d196e071b2dc1db47702085469396f2b956820Chris Forbes    if (!pPipeline->graphicsPipelineCI.pRasterizationState ||
99029d196e071b2dc1db47702085469396f2b956820Chris Forbes        (pPipeline->graphicsPipelineCI.pRasterizationState->rasterizerDiscardEnable == VK_FALSE)) {
99129d196e071b2dc1db47702085469396f2b956820Chris Forbes        VkSampleCountFlagBits pso_num_samples = getNumSamples(pPipeline);
99229d196e071b2dc1db47702085469396f2b956820Chris Forbes        if (pCB->activeRenderPass) {
993fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes            auto const render_pass_info = pCB->activeRenderPass->createInfo.ptr();
99429d196e071b2dc1db47702085469396f2b956820Chris Forbes            const VkSubpassDescription *subpass_desc = &render_pass_info->pSubpasses[pCB->activeSubpass];
99529d196e071b2dc1db47702085469396f2b956820Chris Forbes            uint32_t i;
99676957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes            unsigned subpass_num_samples = 0;
9970a7ed0466d3d3c6c71be07d66c200482d9a9d073Chris Forbes
99829d196e071b2dc1db47702085469396f2b956820Chris Forbes            for (i = 0; i < subpass_desc->colorAttachmentCount; i++) {
99976957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes                auto attachment = subpass_desc->pColorAttachments[i].attachment;
100076957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes                if (attachment != VK_ATTACHMENT_UNUSED)
100176957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes                    subpass_num_samples |= (unsigned)render_pass_info->pAttachments[attachment].samples;
100229d196e071b2dc1db47702085469396f2b956820Chris Forbes            }
10030a7ed0466d3d3c6c71be07d66c200482d9a9d073Chris Forbes
100476957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes            if (subpass_desc->pDepthStencilAttachment &&
100576957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes                subpass_desc->pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) {
100676957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes                auto attachment = subpass_desc->pDepthStencilAttachment->attachment;
100776957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes                subpass_num_samples |= (unsigned)render_pass_info->pAttachments[attachment].samples;
100829d196e071b2dc1db47702085469396f2b956820Chris Forbes            }
1009eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young
10100dc3fd4e57b8531638781daa01a2fb5d1048a6fbJamie Madill            if (subpass_num_samples && static_cast<unsigned>(pso_num_samples) != subpass_num_samples) {
10113251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
10129b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                HandleToUint64(pPipeline->pipeline), __LINE__, DRAWSTATE_NUM_SAMPLES_MISMATCH, "DS",
10139b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                "Num samples mismatch! At draw-time in Pipeline (0x%" PRIxLEAST64
10149b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                ") with %u samples while current RenderPass (0x%" PRIxLEAST64 ") w/ %u samples!",
10159b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                HandleToUint64(pPipeline->pipeline), pso_num_samples,
10169b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                HandleToUint64(pCB->activeRenderPass->renderPass), subpass_num_samples);
1017eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young            }
101829d196e071b2dc1db47702085469396f2b956820Chris Forbes        } else {
10193251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
10209b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(pPipeline->pipeline), __LINE__, DRAWSTATE_NUM_SAMPLES_MISMATCH, "DS",
10213251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "No active render pass found at draw-time in Pipeline (0x%" PRIxLEAST64 ")!",
10229b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(pPipeline->pipeline));
1023eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young        }
1024eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young    }
1025528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis    // Verify that PSO creation renderPass is compatible with active renderPass
1026528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis    if (pCB->activeRenderPass) {
1027528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis        std::string err_string;
1028a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis        if ((pCB->activeRenderPass->renderPass != pPipeline->graphicsPipelineCI.renderPass) &&
102951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis            !verify_renderpass_compatibility(dev_data, pCB->activeRenderPass->createInfo.ptr(), pPipeline->render_pass_ci.ptr(),
1030528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis                                             err_string)) {
1031528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis            // renderPass that PSO was created with must be compatible with active renderPass that PSO is being used with
10323251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
10339b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(pPipeline->pipeline), __LINE__, DRAWSTATE_RENDERPASS_INCOMPATIBLE, "DS",
10349b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            "At Draw time the active render pass (0x%" PRIxLEAST64
10359b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            ") is incompatible w/ gfx pipeline "
10369b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            "(0x%" PRIxLEAST64 ") that was created w/ render pass (0x%" PRIxLEAST64 ") due to: %s",
10379b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(pCB->activeRenderPass->renderPass), HandleToUint64(pPipeline->pipeline),
10389b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(pPipeline->graphicsPipelineCI.renderPass), err_string.c_str());
1039528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis        }
1040c307df2953e6b023531a6ef7fd11e3ee2f2c58b0Chris Forbes
1041c307df2953e6b023531a6ef7fd11e3ee2f2c58b0Chris Forbes        if (pPipeline->graphicsPipelineCI.subpass != pCB->activeSubpass) {
10423251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
10439b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(pPipeline->pipeline), __LINE__, DRAWSTATE_RENDERPASS_INCOMPATIBLE, "DS",
10449b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            "Pipeline was built for subpass %u but used in subpass %u", pPipeline->graphicsPipelineCI.subpass,
10453251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            pCB->activeSubpass);
1046c307df2953e6b023531a6ef7fd11e3ee2f2c58b0Chris Forbes        }
1047528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis    }
104829d196e071b2dc1db47702085469396f2b956820Chris Forbes    // TODO : Add more checks here
104929d196e071b2dc1db47702085469396f2b956820Chris Forbes
10503251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
1051eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young}
1052eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young
1053d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes// For given cvdescriptorset::DescriptorSet, verify that its Set is compatible w/ the setLayout corresponding to
1054d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes// pipelineLayout[layoutIndex]
1055d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbesstatic bool verify_set_layout_compatibility(const cvdescriptorset::DescriptorSet *descriptor_set,
1056d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes                                            PIPELINE_LAYOUT_NODE const *pipeline_layout, const uint32_t layoutIndex,
1057d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes                                            string &errorMsg) {
1058d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes    auto num_sets = pipeline_layout->set_layouts.size();
1059d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes    if (layoutIndex >= num_sets) {
1060d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes        stringstream errorStr;
1061d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes        errorStr << "VkPipelineLayout (" << pipeline_layout->layout << ") only contains " << num_sets
1062d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes                 << " setLayouts corresponding to sets 0-" << num_sets - 1 << ", but you're attempting to bind set to index "
1063d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes                 << layoutIndex;
1064d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes        errorMsg = errorStr.str();
1065d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes        return false;
1066d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes    }
1067d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes    auto layout_node = pipeline_layout->set_layouts[layoutIndex];
106888224335ef7965e89477c393331ef5fa628a9335Tobin Ehlis    return descriptor_set->IsCompatible(layout_node.get(), &errorMsg);
1069d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes}
1070d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes
10715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Validate overall state at the time of a draw call
107251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool ValidateDrawState(layer_data *dev_data, GLOBAL_CB_NODE *cb_node, const bool indexed,
10734f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes                              const VkPipelineBindPoint bind_point, const char *function,
10744f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes                              UNIQUE_VALIDATION_ERROR_CODE const msg_code) {
1075e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool result = false;
10761c130ea631a82716dc7334de17767536525f2292Tobin Ehlis    auto const &state = cb_node->lastBound[bind_point];
10774c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis    PIPELINE_STATE *pPipe = state.pipeline_state;
107822fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis    if (nullptr == pPipe) {
107922fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis        result |= log_msg(
1080df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski            dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
10819b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus            HandleToUint64(cb_node->commandBuffer), __LINE__, DRAWSTATE_INVALID_PIPELINE, "DS",
108222fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis            "At Draw/Dispatch time no valid VkPipeline is bound! This is illegal. Please bind one with vkCmdBindPipeline().");
108322fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis        // Early return as any further checks below will be busted w/o a pipeline
1084cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        if (result) return true;
108522fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis    }
10863d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis    // First check flag states
10871c130ea631a82716dc7334de17767536525f2292Tobin Ehlis    if (VK_PIPELINE_BIND_POINT_GRAPHICS == bind_point)
108851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis        result = validate_draw_state_flags(dev_data, cb_node, pPipe, indexed, msg_code);
10897a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis
10905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Now complete other state checks
109169b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis    if (VK_NULL_HANDLE != state.pipeline_layout.layout) {
109222fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis        string errorString;
109369b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis        auto pipeline_layout = pPipe->pipeline_layout;
1094169c4506062f06d6676eb4da3c9e0437d1d9d659Chris Forbes
10951c130ea631a82716dc7334de17767536525f2292Tobin Ehlis        for (const auto &set_binding_pair : pPipe->active_slots) {
10961c130ea631a82716dc7334de17767536525f2292Tobin Ehlis            uint32_t setIndex = set_binding_pair.first;
109722fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis            // If valid set is not bound throw an error
109822fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis            if ((state.boundDescriptorSets.size() <= setIndex) || (!state.boundDescriptorSets[setIndex])) {
10999b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                result |=
11009b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
11019b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(cb_node->commandBuffer), __LINE__, DRAWSTATE_DESCRIPTOR_SET_NOT_BOUND, "DS",
11029b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            "VkPipeline 0x%" PRIxLEAST64 " uses set #%u but that set is not bound.",
11039b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(pPipe->pipeline), setIndex);
110412b7fc342b53fbdd399aae4a85959e37685936acChris Forbes            } else if (!verify_set_layout_compatibility(state.boundDescriptorSets[setIndex], &pipeline_layout, setIndex,
110569b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis                                                        errorString)) {
110669b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis                // Set is bound but not compatible w/ overlapping pipeline_layout from PSO
110771511c5a10533c910bfe62c3bcf58e2a4054e7acTobin Ehlis                VkDescriptorSet setHandle = state.boundDescriptorSets[setIndex]->GetSet();
110822fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis                result |=
110951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
11109b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(setHandle), __LINE__, DRAWSTATE_PIPELINE_LAYOUTS_INCOMPATIBLE, "DS",
1111414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                            "VkDescriptorSet (0x%" PRIxLEAST64
1112414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                            ") bound as set #%u is not compatible with overlapping VkPipelineLayout 0x%" PRIxLEAST64 " due to: %s",
11139b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(setHandle), setIndex, HandleToUint64(pipeline_layout.layout), errorString.c_str());
1114cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            } else {  // Valid set is bound and layout compatible, validate that it's updated
111522fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis                // Pull the set node
11161c130ea631a82716dc7334de17767536525f2292Tobin Ehlis                cvdescriptorset::DescriptorSet *descriptor_set = state.boundDescriptorSets[setIndex];
11177433ab60c7ff16d37edb0f8b17b606ccd363e210Tobin Ehlis                // Validate the draw-time state for this descriptor set
11187433ab60c7ff16d37edb0f8b17b606ccd363e210Tobin Ehlis                std::string err_str;
11190db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis                if (!descriptor_set->ValidateDrawState(set_binding_pair.second, state.dynamicOffsets[setIndex], cb_node, function,
11200db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis                                                       &err_str)) {
11211c130ea631a82716dc7334de17767536525f2292Tobin Ehlis                    auto set = descriptor_set->GetSet();
11220db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis                    result |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
11239b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                      VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, HandleToUint64(set), __LINE__,
11249b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                      DRAWSTATE_DESCRIPTOR_SET_NOT_UPDATED, "DS",
11250db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis                                      "Descriptor set 0x%" PRIxLEAST64 " encountered the following validation error at %s time: %s",
11269b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                      HandleToUint64(set), function, err_str.c_str());
11277433ab60c7ff16d37edb0f8b17b606ccd363e210Tobin Ehlis                }
11285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
112922fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis        }
113022fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis    }
1131eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young
1132eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young    // Check general pipeline state that needs to be validated at drawtime
113351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    if (VK_PIPELINE_BIND_POINT_GRAPHICS == bind_point) result |= ValidatePipelineDrawtimeState(dev_data, state, cb_node, pPipe);
1134eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young
11355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
11365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
11375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
113851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic void UpdateDrawState(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, const VkPipelineBindPoint bind_point) {
11391c130ea631a82716dc7334de17767536525f2292Tobin Ehlis    auto const &state = cb_state->lastBound[bind_point];
1140ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis    PIPELINE_STATE *pPipe = state.pipeline_state;
1141ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis    if (VK_NULL_HANDLE != state.pipeline_layout.layout) {
11421c130ea631a82716dc7334de17767536525f2292Tobin Ehlis        for (const auto &set_binding_pair : pPipe->active_slots) {
11431c130ea631a82716dc7334de17767536525f2292Tobin Ehlis            uint32_t setIndex = set_binding_pair.first;
1144ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis            // Pull the set node
11451c130ea631a82716dc7334de17767536525f2292Tobin Ehlis            cvdescriptorset::DescriptorSet *descriptor_set = state.boundDescriptorSets[setIndex];
1146ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis            // Bind this set and its active descriptor resources to the command buffer
11471c130ea631a82716dc7334de17767536525f2292Tobin Ehlis            descriptor_set->BindCommandBuffer(cb_state, set_binding_pair.second);
11487433ab60c7ff16d37edb0f8b17b606ccd363e210Tobin Ehlis            // For given active slots record updated images & buffers
11491c130ea631a82716dc7334de17767536525f2292Tobin Ehlis            descriptor_set->GetStorageUpdates(set_binding_pair.second, &cb_state->updateBuffers, &cb_state->updateImages);
1150ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis        }
1151ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis    }
115258b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis    if (pPipe->vertexBindingDescriptions.size() > 0) {
115358b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis        cb_state->vertex_buffer_used = true;
115458b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis    }
1155ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis}
1156ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis
1157a27508babf63d50aea75883a3702979193c23683Mark Young// Validate HW line width capabilities prior to setting requested line width.
115806727c7f56d1080aff506a9ae1ae9d8c174b3e9dMark Lobodzinskistatic bool verifyLineWidth(layer_data *dev_data, DRAW_STATE_ERROR dsError, VulkanObjectType object_type, const uint64_t &target,
115906727c7f56d1080aff506a9ae1ae9d8c174b3e9dMark Lobodzinski                            float lineWidth) {
11603251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
1161a27508babf63d50aea75883a3702979193c23683Mark Young
1162a27508babf63d50aea75883a3702979193c23683Mark Young    // First check to see if the physical device supports wide lines.
116351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    if ((VK_FALSE == dev_data->enabled_features.wideLines) && (1.0f != lineWidth)) {
11643251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, get_debug_report_enum[object_type], target, __LINE__,
11653251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        dsError, "DS",
11663251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "Attempt to set lineWidth to %f but physical device wideLines feature "
11673251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "not supported/enabled so lineWidth must be 1.0f!",
11683251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        lineWidth);
1169a27508babf63d50aea75883a3702979193c23683Mark Young    } else {
1170a27508babf63d50aea75883a3702979193c23683Mark Young        // Otherwise, make sure the width falls in the valid range.
117151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis        if ((dev_data->phys_dev_properties.properties.limits.lineWidthRange[0] > lineWidth) ||
117251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis            (dev_data->phys_dev_properties.properties.limits.lineWidthRange[1] < lineWidth)) {
11733251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, get_debug_report_enum[object_type], target,
11743251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            __LINE__, dsError, "DS",
11753251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "Attempt to set lineWidth to %f but physical device limits line width "
11763251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "to between [%f, %f]!",
11773251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            lineWidth, dev_data->phys_dev_properties.properties.limits.lineWidthRange[0],
11783251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            dev_data->phys_dev_properties.properties.limits.lineWidthRange[1]);
1179a27508babf63d50aea75883a3702979193c23683Mark Young        }
1180a27508babf63d50aea75883a3702979193c23683Mark Young    }
1181a27508babf63d50aea75883a3702979193c23683Mark Young
11823251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
1183a27508babf63d50aea75883a3702979193c23683Mark Young}
1184a27508babf63d50aea75883a3702979193c23683Mark Young
11852f521eee4ccb1c84512ea767880df8f38751c0d4Chris Forbesstatic bool ValidatePipelineLocked(layer_data *dev_data, std::vector<PIPELINE_STATE *> const &pPipelines, int pipelineIndex) {
11863251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
11875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
11884c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis    PIPELINE_STATE *pPipeline = pPipelines[pipelineIndex];
11895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
11905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // If create derivative bit is set, check that we've specified a base
11915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // pipeline correctly, and that the base pipeline was created to allow
11925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // derivatives.
11935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pPipeline->graphicsPipelineCI.flags & VK_PIPELINE_CREATE_DERIVATIVE_BIT) {
11944c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis        PIPELINE_STATE *pBasePipeline = nullptr;
11955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (!((pPipeline->graphicsPipelineCI.basePipelineHandle != VK_NULL_HANDLE) ^
11965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis              (pPipeline->graphicsPipelineCI.basePipelineIndex != -1))) {
1197315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis            // This check is a superset of VALIDATION_ERROR_096005a8 and VALIDATION_ERROR_096005aa
11983251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
11999b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(pPipeline->pipeline), __LINE__, DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS",
12009b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            "Invalid Pipeline CreateInfo: exactly one of base pipeline index and handle must be specified");
12015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else if (pPipeline->graphicsPipelineCI.basePipelineIndex != -1) {
12025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (pPipeline->graphicsPipelineCI.basePipelineIndex >= pipelineIndex) {
12033251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |=
1204df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1205315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_208005a0, "DS",
1206f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt                            "Invalid Pipeline CreateInfo: base pipeline must occur earlier in array than derivative pipeline. %s",
1207315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            validation_error_map[VALIDATION_ERROR_208005a0]);
12085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            } else {
12095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                pBasePipeline = pPipelines[pPipeline->graphicsPipelineCI.basePipelineIndex];
12105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
12115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else if (pPipeline->graphicsPipelineCI.basePipelineHandle != VK_NULL_HANDLE) {
121251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis            pBasePipeline = getPipelineState(dev_data, pPipeline->graphicsPipelineCI.basePipelineHandle);
12135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
12145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
12155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (pBasePipeline && !(pBasePipeline->graphicsPipelineCI.flags & VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT)) {
12163251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
12179b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(pPipeline->pipeline), __LINE__, DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS",
12189b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            "Invalid Pipeline CreateInfo: base pipeline does not allow derivatives.");
12195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
12205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
12215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
1222c3e70f769bd4aa0988652050444d57cab4925c16Chris Forbes    return skip;
1223c3e70f769bd4aa0988652050444d57cab4925c16Chris Forbes}
1224c3e70f769bd4aa0988652050444d57cab4925c16Chris Forbes
1225c3e70f769bd4aa0988652050444d57cab4925c16Chris Forbes// UNLOCKED pipeline validation. DO NOT lookup objects in the layer_data->* maps in this function.
1226c3e70f769bd4aa0988652050444d57cab4925c16Chris Forbesstatic bool ValidatePipelineUnlocked(layer_data *dev_data, std::vector<PIPELINE_STATE *> const &pPipelines, int pipelineIndex) {
1227c3e70f769bd4aa0988652050444d57cab4925c16Chris Forbes    bool skip = false;
1228c3e70f769bd4aa0988652050444d57cab4925c16Chris Forbes
1229c3e70f769bd4aa0988652050444d57cab4925c16Chris Forbes        PIPELINE_STATE *pPipeline = pPipelines[pipelineIndex];
1230c3e70f769bd4aa0988652050444d57cab4925c16Chris Forbes
1231fa30cd33537b2773dae129822b4e7c654a027929Chris Forbes    // Ensure the subpass index is valid. If not, then validate_and_capture_pipeline_shader_state
1232fa30cd33537b2773dae129822b4e7c654a027929Chris Forbes    // produces nonsense errors that confuse users. Other layers should already
1233fa30cd33537b2773dae129822b4e7c654a027929Chris Forbes    // emit errors for renderpass being invalid.
1234146a87545e7b707b1dbddbd9cb8b41869ad402ccChris Forbes    auto subpass_desc = &pPipeline->render_pass_ci.pSubpasses[pPipeline->graphicsPipelineCI.subpass];
1235146a87545e7b707b1dbddbd9cb8b41869ad402ccChris Forbes    if (pPipeline->graphicsPipelineCI.subpass >= pPipeline->render_pass_ci.subpassCount) {
1236fa30cd33537b2773dae129822b4e7c654a027929Chris Forbes        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1237fa30cd33537b2773dae129822b4e7c654a027929Chris Forbes                        HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_096005ee, "DS",
1238fa30cd33537b2773dae129822b4e7c654a027929Chris Forbes                        "Invalid Pipeline CreateInfo State: Subpass index %u "
1239fa30cd33537b2773dae129822b4e7c654a027929Chris Forbes                            "is out of range for this renderpass (0..%u). %s",
1240146a87545e7b707b1dbddbd9cb8b41869ad402ccChris Forbes                        pPipeline->graphicsPipelineCI.subpass, pPipeline->render_pass_ci.subpassCount - 1,
1241fa30cd33537b2773dae129822b4e7c654a027929Chris Forbes                        validation_error_map[VALIDATION_ERROR_096005ee]);
1242146a87545e7b707b1dbddbd9cb8b41869ad402ccChris Forbes        subpass_desc = nullptr;
1243fa30cd33537b2773dae129822b4e7c654a027929Chris Forbes    }
1244fa30cd33537b2773dae129822b4e7c654a027929Chris Forbes
12455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pPipeline->graphicsPipelineCI.pColorBlendState != NULL) {
1246fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis        const safe_VkPipelineColorBlendStateCreateInfo *color_blend_state = pPipeline->graphicsPipelineCI.pColorBlendState;
1247fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis        if (color_blend_state->attachmentCount != subpass_desc->colorAttachmentCount) {
12483251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(
124951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis                dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1250315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_096005d4, "DS",
1251fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis                "vkCreateGraphicsPipelines(): Render pass (0x%" PRIxLEAST64
1252fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis                ") subpass %u has colorAttachmentCount of %u which doesn't match the pColorBlendState->attachmentCount of %u. %s",
12539b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                HandleToUint64(pPipeline->graphicsPipelineCI.renderPass), pPipeline->graphicsPipelineCI.subpass,
1254fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis                subpass_desc->colorAttachmentCount, color_blend_state->attachmentCount,
1255315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                validation_error_map[VALIDATION_ERROR_096005d4]);
1256fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis        }
125751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis        if (!dev_data->enabled_features.independentBlend) {
12583d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis            if (pPipeline->attachments.size() > 1) {
125926c548826ff0f83d12c769b51e7d6f76d1265c0eChris Forbes                VkPipelineColorBlendAttachmentState *pAttachments = &pPipeline->attachments[0];
1260c7bd67f06427b08ba65cdf2dd529c8234beebdd5Mark Lobodzinski                for (size_t i = 1; i < pPipeline->attachments.size(); i++) {
126106811df0256552cd7da9d7297672af377463fc4aMark Mueller                    // Quoting the spec: "If [the independent blend] feature is not enabled, the VkPipelineColorBlendAttachmentState
126206811df0256552cd7da9d7297672af377463fc4aMark Mueller                    // settings for all color attachments must be identical." VkPipelineColorBlendAttachmentState contains
126306811df0256552cd7da9d7297672af377463fc4aMark Mueller                    // only attachment state, so memcmp is best suited for the comparison
126406811df0256552cd7da9d7297672af377463fc4aMark Mueller                    if (memcmp(static_cast<const void *>(pAttachments), static_cast<const void *>(&pAttachments[i]),
126506811df0256552cd7da9d7297672af377463fc4aMark Mueller                               sizeof(pAttachments[0]))) {
12663251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        skip |=
1267df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                            log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1268315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_0f4004ba, "DS",
1269df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                                    "Invalid Pipeline CreateInfo: If independent blend feature not "
1270df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                                    "enabled, all elements of pAttachments must be identical. %s",
1271315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    validation_error_map[VALIDATION_ERROR_0f4004ba]);
127206811df0256552cd7da9d7297672af377463fc4aMark Mueller                        break;
1273c7bd67f06427b08ba65cdf2dd529c8234beebdd5Mark Lobodzinski                    }
12745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
12755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
12765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
127751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis        if (!dev_data->enabled_features.logicOp && (pPipeline->graphicsPipelineCI.pColorBlendState->logicOpEnable != VK_FALSE)) {
12783251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |=
1279df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1280315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_0f4004bc, "DS",
1281f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt                        "Invalid Pipeline CreateInfo: If logic operations feature not enabled, logicOpEnable must be VK_FALSE. %s",
1282315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_0f4004bc]);
12835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
12845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
12855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
128659ae0ccadec962d9ca2cce7584fad6c57c1a4458Tobin Ehlis    if (validate_and_capture_pipeline_shader_state(dev_data, pPipeline)) {
12873251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip = true;
12885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
128952156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes    // Each shader's stage must be unique
129052156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes    if (pPipeline->duplicate_shaders) {
129152156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes        for (uint32_t stage = VK_SHADER_STAGE_VERTEX_BIT; stage & VK_SHADER_STAGE_ALL_GRAPHICS; stage <<= 1) {
129252156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes            if (pPipeline->duplicate_shaders & stage) {
12939b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
12949b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                HandleToUint64(pPipeline->pipeline), __LINE__, DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS",
12959b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                "Invalid Pipeline CreateInfo State: Multiple shaders provided for stage %s",
12969b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                string_VkShaderStageFlagBits(VkShaderStageFlagBits(stage)));
129752156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes            }
129852156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes        }
129952156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes    }
13005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // VS is required
13015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (!(pPipeline->active_shaders & VK_SHADER_STAGE_VERTEX_BIT)) {
1302315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1303315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_096005ae, "DS",
1304315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        "Invalid Pipeline CreateInfo State: Vertex Shader required. %s",
1305315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_096005ae]);
13065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
13075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Either both or neither TC/TE shaders should be defined
13083067e46adf202d2cc3ce1e06909dc7fadf0c8c3bCort Stratton    bool has_control = (pPipeline->active_shaders & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0;
13093067e46adf202d2cc3ce1e06909dc7fadf0c8c3bCort Stratton    bool has_eval = (pPipeline->active_shaders & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0;
13103067e46adf202d2cc3ce1e06909dc7fadf0c8c3bCort Stratton    if (has_control && !has_eval) {
13113251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1312315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_096005b2, "DS",
13133251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "Invalid Pipeline CreateInfo State: TE and TC shaders must be included or excluded as a pair. %s",
1314315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_096005b2]);
1315f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt    }
13163067e46adf202d2cc3ce1e06909dc7fadf0c8c3bCort Stratton    if (!has_control && has_eval) {
13173251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1318315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_096005b4, "DS",
13193251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "Invalid Pipeline CreateInfo State: TE and TC shaders must be included or excluded as a pair. %s",
1320315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_096005b4]);
13215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
13225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Compute shaders should be specified independent of Gfx shaders
1323f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt    if (pPipeline->active_shaders & VK_SHADER_STAGE_COMPUTE_BIT) {
13243251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1325315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_096005b0, "DS",
13263251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "Invalid Pipeline CreateInfo State: Do not specify Compute Shader for Gfx Pipeline. %s",
1327315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_096005b0]);
13285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
13295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // VK_PRIMITIVE_TOPOLOGY_PATCH_LIST primitive topology is only valid for tessellation pipelines.
13305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Mismatching primitive topology and tessellation fails graphics pipeline creation.
13313067e46adf202d2cc3ce1e06909dc7fadf0c8c3bCort Stratton    if (has_control && has_eval &&
1332ca546210846c65808717f8875deae39bd227c240Tobin Ehlis        (!pPipeline->graphicsPipelineCI.pInputAssemblyState ||
1333ca546210846c65808717f8875deae39bd227c240Tobin Ehlis         pPipeline->graphicsPipelineCI.pInputAssemblyState->topology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST)) {
13343251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1335315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_096005c0, "DS",
13363251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "Invalid Pipeline CreateInfo State: "
13373251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "VK_PRIMITIVE_TOPOLOGY_PATCH_LIST must be set as IA "
13383251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "topology for tessellation pipelines. %s",
1339315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_096005c0]);
13405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
1341ca546210846c65808717f8875deae39bd227c240Tobin Ehlis    if (pPipeline->graphicsPipelineCI.pInputAssemblyState &&
1342ca546210846c65808717f8875deae39bd227c240Tobin Ehlis        pPipeline->graphicsPipelineCI.pInputAssemblyState->topology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST) {
13433067e46adf202d2cc3ce1e06909dc7fadf0c8c3bCort Stratton        if (!has_control || !has_eval) {
13443251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1345315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_096005c2, "DS",
13463251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "Invalid Pipeline CreateInfo State: "
13473251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "VK_PRIMITIVE_TOPOLOGY_PATCH_LIST primitive "
13483251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "topology is only valid for tessellation pipelines. %s",
1349315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            validation_error_map[VALIDATION_ERROR_096005c2]);
13505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
13515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
1352f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt
13536b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen    // If a rasterization state is provided...
1354a27508babf63d50aea75883a3702979193c23683Mark Young    if (pPipeline->graphicsPipelineCI.pRasterizationState) {
13556b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen        // Make sure that the line width conforms to the HW.
1356a27508babf63d50aea75883a3702979193c23683Mark Young        if (!isDynamic(pPipeline, VK_DYNAMIC_STATE_LINE_WIDTH)) {
13579b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus            skip |=
13589b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                verifyLineWidth(dev_data, DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, kVulkanObjectTypePipeline,
13599b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                HandleToUint64(pPipeline->pipeline), pPipeline->graphicsPipelineCI.pRasterizationState->lineWidth);
1360a27508babf63d50aea75883a3702979193c23683Mark Young        }
13615dcdd90e54199dfeb29938a3a03d998397c22664Chris Forbes
136258c5552c73679f81f57a64a809f7d4d6d52f4ce3Mark Lobodzinski        if ((pPipeline->graphicsPipelineCI.pRasterizationState->depthClampEnable == VK_TRUE) &&
136358c5552c73679f81f57a64a809f7d4d6d52f4ce3Mark Lobodzinski            (!dev_data->enabled_features.depthClamp)) {
13643251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1365315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_1020061c, "DS",
13663251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "vkCreateGraphicsPipelines(): the depthClamp device feature is disabled: the depthClampEnable "
13673251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "member of the VkPipelineRasterizationStateCreateInfo structure must be set to VK_FALSE. %s",
1368315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            validation_error_map[VALIDATION_ERROR_1020061c]);
136958c5552c73679f81f57a64a809f7d4d6d52f4ce3Mark Lobodzinski        }
137058c5552c73679f81f57a64a809f7d4d6d52f4ce3Mark Lobodzinski
1371434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski        if (!isDynamic(pPipeline, VK_DYNAMIC_STATE_DEPTH_BIAS) &&
1372434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski            (pPipeline->graphicsPipelineCI.pRasterizationState->depthBiasClamp != 0.0) &&
1373434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski            (!dev_data->enabled_features.depthBiasClamp)) {
13743251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
13759b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(pPipeline->pipeline), __LINE__, DRAWSTATE_INVALID_FEATURE, "DS",
13763251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "vkCreateGraphicsPipelines(): the depthBiasClamp device feature is disabled: the depthBiasClamp "
13773251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "member of the VkPipelineRasterizationStateCreateInfo structure must be set to 0.0 unless the "
13783251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "VK_DYNAMIC_STATE_DEPTH_BIAS dynamic state is enabled");
1379434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski        }
1380434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski
13816b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen        // If rasterization is enabled...
13826b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen        if (pPipeline->graphicsPipelineCI.pRasterizationState->rasterizerDiscardEnable == VK_FALSE) {
1383148e8028deee2b4b00ccd4a69210897add328265Mark Lobodzinski            if ((pPipeline->graphicsPipelineCI.pMultisampleState->alphaToOneEnable == VK_TRUE) &&
1384148e8028deee2b4b00ccd4a69210897add328265Mark Lobodzinski                (!dev_data->enabled_features.alphaToOne)) {
13853251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1386315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_10000622, "DS",
13873251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "vkCreateGraphicsPipelines(): the alphaToOne device feature is disabled: the alphaToOneEnable "
13883251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "member of the VkPipelineMultisampleStateCreateInfo structure must be set to VK_FALSE. %s",
1389315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                validation_error_map[VALIDATION_ERROR_10000622]);
1390148e8028deee2b4b00ccd4a69210897add328265Mark Lobodzinski            }
1391148e8028deee2b4b00ccd4a69210897add328265Mark Lobodzinski
13926b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen            // If subpass uses a depth/stencil attachment, pDepthStencilState must be a pointer to a valid structure
13936b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen            if (subpass_desc && subpass_desc->pDepthStencilAttachment &&
13946b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen                subpass_desc->pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) {
13956b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen                if (!pPipeline->graphicsPipelineCI.pDepthStencilState) {
13963251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1397315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_096005e0, "DS",
13983251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    "Invalid Pipeline CreateInfo State: pDepthStencilState is NULL when rasterization is "
13993251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    "enabled and subpass uses a depth/stencil attachment. %s",
1400315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    validation_error_map[VALIDATION_ERROR_096005e0]);
14019580629edfc5154cc9e36974cca12966fbd748b9Mark Lobodzinski
14029580629edfc5154cc9e36974cca12966fbd748b9Mark Lobodzinski                } else if ((pPipeline->graphicsPipelineCI.pDepthStencilState->depthBoundsTestEnable == VK_TRUE) &&
14039580629edfc5154cc9e36974cca12966fbd748b9Mark Lobodzinski                           (!dev_data->enabled_features.depthBounds)) {
14043251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= log_msg(
1405df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                        dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
14069b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        HandleToUint64(pPipeline->pipeline), __LINE__, DRAWSTATE_INVALID_FEATURE, "DS",
14079580629edfc5154cc9e36974cca12966fbd748b9Mark Lobodzinski                        "vkCreateGraphicsPipelines(): the depthBounds device feature is disabled: the depthBoundsTestEnable "
14089580629edfc5154cc9e36974cca12966fbd748b9Mark Lobodzinski                        "member of the VkPipelineDepthStencilStateCreateInfo structure must be set to VK_FALSE.");
14096b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen                }
14105dcdd90e54199dfeb29938a3a03d998397c22664Chris Forbes            }
1411326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen
1412326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen            // If subpass uses color attachments, pColorBlendState must be valid pointer
1413326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen            if (subpass_desc) {
1414326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen                uint32_t color_attachment_count = 0;
1415326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen                for (uint32_t i = 0; i < subpass_desc->colorAttachmentCount; ++i) {
1416326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen                    if (subpass_desc->pColorAttachments[i].attachment != VK_ATTACHMENT_UNUSED) {
1417326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen                        ++color_attachment_count;
1418326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen                    }
1419326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen                }
1420326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen                if (color_attachment_count > 0 && pPipeline->graphicsPipelineCI.pColorBlendState == nullptr) {
14213251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1422315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_096005e2, "DS",
14233251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    "Invalid Pipeline CreateInfo State: pColorBlendState is NULL when rasterization is "
14243251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    "enabled and subpass uses color attachments. %s",
1425315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    validation_error_map[VALIDATION_ERROR_096005e2]);
1426326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen                }
1427326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen            }
14285dcdd90e54199dfeb29938a3a03d998397c22664Chris Forbes        }
14295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
14306b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen
1431740a9cdda3aa9cc7a4124184bd58146e6e99d772Chris Forbes    auto vi = pPipeline->graphicsPipelineCI.pVertexInputState;
1432740a9cdda3aa9cc7a4124184bd58146e6e99d772Chris Forbes    if (vi != NULL) {
1433740a9cdda3aa9cc7a4124184bd58146e6e99d772Chris Forbes        for (uint32_t j = 0; j < vi->vertexAttributeDescriptionCount; j++) {
1434740a9cdda3aa9cc7a4124184bd58146e6e99d772Chris Forbes            VkFormat format = vi->pVertexAttributeDescriptions[j].format;
1435740a9cdda3aa9cc7a4124184bd58146e6e99d772Chris Forbes            // Internal call to get format info.  Still goes through layers, could potentially go directly to ICD.
1436740a9cdda3aa9cc7a4124184bd58146e6e99d772Chris Forbes            VkFormatProperties properties;
1437740a9cdda3aa9cc7a4124184bd58146e6e99d772Chris Forbes            dev_data->instance_data->dispatch_table.GetPhysicalDeviceFormatProperties(dev_data->physical_device, format, &properties);
1438740a9cdda3aa9cc7a4124184bd58146e6e99d772Chris Forbes            if ((properties.bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) == 0) {
1439740a9cdda3aa9cc7a4124184bd58146e6e99d772Chris Forbes                skip |= log_msg(
1440740a9cdda3aa9cc7a4124184bd58146e6e99d772Chris Forbes                    dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
1441740a9cdda3aa9cc7a4124184bd58146e6e99d772Chris Forbes                    __LINE__, VALIDATION_ERROR_14a004de, "IMAGE",
1442740a9cdda3aa9cc7a4124184bd58146e6e99d772Chris Forbes                    "vkCreateGraphicsPipelines: pCreateInfo[%d].pVertexInputState->vertexAttributeDescriptions[%d].format "
1443740a9cdda3aa9cc7a4124184bd58146e6e99d772Chris Forbes                        "(%s) is not a supported vertex buffer format. %s",
1444740a9cdda3aa9cc7a4124184bd58146e6e99d772Chris Forbes                    pipelineIndex, j, string_VkFormat(format), validation_error_map[VALIDATION_ERROR_14a004de]);
1445740a9cdda3aa9cc7a4124184bd58146e6e99d772Chris Forbes            }
1446740a9cdda3aa9cc7a4124184bd58146e6e99d772Chris Forbes        }
1447740a9cdda3aa9cc7a4124184bd58146e6e99d772Chris Forbes    }
1448740a9cdda3aa9cc7a4124184bd58146e6e99d772Chris Forbes
14493251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
14505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
14515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
14525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Free the Pipeline nodes
145351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic void deletePipelines(layer_data *dev_data) {
145451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    if (dev_data->pipelineMap.size() <= 0) return;
145551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    for (auto &pipe_map_pair : dev_data->pipelineMap) {
1456ca546210846c65808717f8875deae39bd227c240Tobin Ehlis        delete pipe_map_pair.second;
14575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
145851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    dev_data->pipelineMap.clear();
14595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
14605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
14615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Block of code at start here specifically for managing/tracking DSs
14625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
14635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Return Pool node ptr for specified pool or else NULL
14649a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisDESCRIPTOR_POOL_STATE *GetDescriptorPoolState(const layer_data *dev_data, const VkDescriptorPool pool) {
1465bb7ea477706f90eb2a72887f652795bc79f60ddeTobin Ehlis    auto pool_it = dev_data->descriptorPoolMap.find(pool);
1466bb7ea477706f90eb2a72887f652795bc79f60ddeTobin Ehlis    if (pool_it == dev_data->descriptorPoolMap.end()) {
14675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return NULL;
14685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
1469bb7ea477706f90eb2a72887f652795bc79f60ddeTobin Ehlis    return pool_it->second;
14705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
14715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
14725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Validate that given set is valid and that it's not being used by an in-flight CmdBuffer
14735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// func_str is the name of the calling function
1474e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves// Return false if no errors occur
1475e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves// Return true if validation error occurs and callback returns true (to skip upcoming API call down the chain)
14760dcd0f7b37456e2e552d37094ba503c0d089b906Tobin Ehlisstatic bool validateIdleDescriptorSet(const layer_data *dev_data, VkDescriptorSet set, std::string func_str) {
1477cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.idle_descriptor_set) return false;
14783251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
14790dcd0f7b37456e2e552d37094ba503c0d089b906Tobin Ehlis    auto set_node = dev_data->setMap.find(set);
14800dcd0f7b37456e2e552d37094ba503c0d089b906Tobin Ehlis    if (set_node == dev_data->setMap.end()) {
14813251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
14829b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        HandleToUint64(set), __LINE__, DRAWSTATE_DOUBLE_DESTROY, "DS",
14833251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "Cannot call %s() on descriptor set 0x%" PRIxLEAST64 " that has not been allocated.", func_str.c_str(),
14849b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        HandleToUint64(set));
14855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    } else {
14861c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis        // TODO : This covers various error cases so should pass error enum into this function and use passed in enum here
14875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (set_node->second->in_use.load()) {
14883251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
1489315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(set), __LINE__, VALIDATION_ERROR_2860026a, "DS",
14903251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "Cannot call %s() on descriptor set 0x%" PRIxLEAST64 " that is in use by a command buffer. %s",
1491315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            func_str.c_str(), HandleToUint64(set), validation_error_map[VALIDATION_ERROR_2860026a]);
14925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
14935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
14943251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
14955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
1496f80bf38f4fb3f177b3e1be11b7b1c5edcdbf7d9bChris Forbes
1497e6651096ed8f07840447783c66827cc16d659a49Tobin Ehlis// Remove set from setMap and delete the set
14989dd448578d59cb5ce692e833ba230783b30f3550Tobin Ehlisstatic void freeDescriptorSet(layer_data *dev_data, cvdescriptorset::DescriptorSet *descriptor_set) {
14999dd448578d59cb5ce692e833ba230783b30f3550Tobin Ehlis    dev_data->setMap.erase(descriptor_set->GetSet());
15009dd448578d59cb5ce692e833ba230783b30f3550Tobin Ehlis    delete descriptor_set;
15019dd448578d59cb5ce692e833ba230783b30f3550Tobin Ehlis}
15025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Free all DS Pools including their Sets & related sub-structs
15035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// NOTE : Calls to this function should be wrapped in mutex
150451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic void deletePools(layer_data *dev_data) {
1505ee7e96d032744c1db89cab21362ac8ecad6eec5aGabríel Arthúr Pétursson    for (auto ii = dev_data->descriptorPoolMap.begin(); ii != dev_data->descriptorPoolMap.end();) {
1506c5f47f0a54e14c47d402aeabc6498d981ecda9ccTobin Ehlis        // Remove this pools' sets from setMap and delete them
1507ee7e96d032744c1db89cab21362ac8ecad6eec5aGabríel Arthúr Pétursson        for (auto ds : ii->second->sets) {
150851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis            freeDescriptorSet(dev_data, ds);
15095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
1510ee7e96d032744c1db89cab21362ac8ecad6eec5aGabríel Arthúr Pétursson        ii->second->sets.clear();
1511ee7e96d032744c1db89cab21362ac8ecad6eec5aGabríel Arthúr Pétursson        delete ii->second;
1512ee7e96d032744c1db89cab21362ac8ecad6eec5aGabríel Arthúr Pétursson        ii = dev_data->descriptorPoolMap.erase(ii);
15135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
15145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
15155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
151651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic void clearDescriptorPool(layer_data *dev_data, const VkDevice device, const VkDescriptorPool pool,
15175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                VkDescriptorPoolResetFlags flags) {
15189a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    DESCRIPTOR_POOL_STATE *pPool = GetDescriptorPoolState(dev_data, pool);
1519de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis    // TODO: validate flags
1520de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis    // For every set off of this pool, clear it, remove from setMap, and free cvdescriptorset::DescriptorSet
1521de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis    for (auto ds : pPool->sets) {
152251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis        freeDescriptorSet(dev_data, ds);
1523de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis    }
1524de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis    pPool->sets.clear();
1525de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis    // Reset available count for each type and available sets for this pool
1526de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis    for (uint32_t i = 0; i < pPool->availableDescriptorTypeCount.size(); ++i) {
1527de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis        pPool->availableDescriptorTypeCount[i] = pPool->maxDescriptorTypeCount[i];
15285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
1529de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis    pPool->availableSets = pPool->maxSets;
15305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
15315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
15325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// For given CB object, fetch associated CB Node from map
15339a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisGLOBAL_CB_NODE *GetCBNode(layer_data const *dev_data, const VkCommandBuffer cb) {
153451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    auto it = dev_data->commandBufferMap.find(cb);
153551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    if (it == dev_data->commandBufferMap.end()) {
15365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return NULL;
15375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
15385121a8dcacb23766ba4455b4eea429f0a3d62099Chris Forbes    return it->second;
15395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
15405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
154129f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis// If a renderpass is active, verify that the given command type is appropriate for current subpass state
154229f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlisbool ValidateCmdSubpassState(const layer_data *dev_data, const GLOBAL_CB_NODE *pCB, const CMD_TYPE cmd_type) {
1543cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (!pCB->activeRenderPass) return false;
15443251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
1545d0d8e333806eaac08bdc87ddeff886dc2b0f09e7Tobin Ehlis    if (pCB->activeSubpassContents == VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS &&
1546d0d8e333806eaac08bdc87ddeff886dc2b0f09e7Tobin Ehlis        (cmd_type != CMD_EXECUTECOMMANDS && cmd_type != CMD_NEXTSUBPASS && cmd_type != CMD_ENDRENDERPASS)) {
15473251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
15489b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        HandleToUint64(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER, "DS",
15493251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "Commands cannot be called in a subpass using secondary command buffers.");
15505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    } else if (pCB->activeSubpassContents == VK_SUBPASS_CONTENTS_INLINE && cmd_type == CMD_EXECUTECOMMANDS) {
15513251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
15529b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        HandleToUint64(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER, "DS",
15533251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "vkCmdExecuteCommands() cannot be called in a subpass using inline commands.");
15545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
15553251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
15565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
15575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
1558e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlisbool ValidateCmdQueueFlags(layer_data *dev_data, const GLOBAL_CB_NODE *cb_node, const char *caller_name,
1559e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis                           VkQueueFlags required_flags, UNIQUE_VALIDATION_ERROR_CODE error_code) {
1560baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt    auto pool = GetCommandPoolNode(dev_data, cb_node->createInfo.commandPool);
1561baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt    if (pool) {
1562baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt        VkQueueFlags queue_flags = dev_data->phys_dev_properties.queue_family_properties[pool->queueFamilyIndex].queueFlags;
1563baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt        if (!(required_flags & queue_flags)) {
1564baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt            string required_flags_string;
1565baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt            for (auto flag : {VK_QUEUE_TRANSFER_BIT, VK_QUEUE_GRAPHICS_BIT, VK_QUEUE_COMPUTE_BIT}) {
1566baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt                if (flag & required_flags) {
1567baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt                    if (required_flags_string.size()) {
1568baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt                        required_flags_string += " or ";
1569baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt                    }
1570baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt                    required_flags_string += string_VkQueueFlagBits(flag);
1571baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt                }
1572baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt            }
1573baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt            return log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
15749b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                           HandleToUint64(cb_node->commandBuffer), __LINE__, error_code, "DS",
1575baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt                           "Cannot call %s on a command buffer allocated from a pool without %s capabilities. %s.", caller_name,
1576baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt                           required_flags_string.c_str(), validation_error_map[error_code]);
1577baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt        }
1578baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt    }
15795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return false;
15805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
15815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
1582d00947f5dcd29a4d8aab59e62f72df50444d2537Chris Forbesstatic char const * GetCauseStr(VK_OBJECT obj) {
1583d00947f5dcd29a4d8aab59e62f72df50444d2537Chris Forbes    if (obj.type == kVulkanObjectTypeDescriptorSet)
1584d00947f5dcd29a4d8aab59e62f72df50444d2537Chris Forbes        return "destroyed or updated";
1585d00947f5dcd29a4d8aab59e62f72df50444d2537Chris Forbes    if (obj.type == kVulkanObjectTypeCommandBuffer)
1586d00947f5dcd29a4d8aab59e62f72df50444d2537Chris Forbes        return "destroyed or rerecorded";
1587d00947f5dcd29a4d8aab59e62f72df50444d2537Chris Forbes    return "destroyed";
1588d00947f5dcd29a4d8aab59e62f72df50444d2537Chris Forbes}
1589d00947f5dcd29a4d8aab59e62f72df50444d2537Chris Forbes
1590e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlisstatic bool ReportInvalidCommandBuffer(layer_data *dev_data, const GLOBAL_CB_NODE *cb_state, const char *call_source) {
1591ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski    bool skip = false;
1592ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski    for (auto obj : cb_state->broken_bindings) {
15937a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski        const char *type_str = object_string[obj.type];
1594d00947f5dcd29a4d8aab59e62f72df50444d2537Chris Forbes        const char *cause_str = GetCauseStr(obj);
1595ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
15969b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        HandleToUint64(cb_state->commandBuffer), __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER, "DS",
1597ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski                        "You are adding %s to command buffer 0x%p that is invalid because bound %s 0x%" PRIxLEAST64 " was %s.",
1598ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski                        call_source, cb_state->commandBuffer, type_str, obj.handle, cause_str);
1599ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski    }
1600ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski    return skip;
1601ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski}
1602ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski
1603623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski// Validate the given command being added to the specified cmd buffer, flagging errors if CB is not in the recording state or if
1604623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski// there's an issue with the Cmd ordering
1605e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlisbool ValidateCmd(layer_data *dev_data, const GLOBAL_CB_NODE *cb_state, const CMD_TYPE cmd, const char *caller_name) {
160633f3623e8124c3a6081b60f68b9d39a19a5840aeChris Forbes    switch (cb_state->state) {
160733f3623e8124c3a6081b60f68b9d39a19a5840aeChris Forbes        case CB_RECORDING:
160833f3623e8124c3a6081b60f68b9d39a19a5840aeChris Forbes            return ValidateCmdSubpassState(dev_data, cb_state, cmd);
160933f3623e8124c3a6081b60f68b9d39a19a5840aeChris Forbes
161046daa701a01b92ae19e3ee9e661d677128fe7e6dChris Forbes        case CB_INVALID_COMPLETE:
161146daa701a01b92ae19e3ee9e661d677128fe7e6dChris Forbes        case CB_INVALID_INCOMPLETE:
161233f3623e8124c3a6081b60f68b9d39a19a5840aeChris Forbes            return ReportInvalidCommandBuffer(dev_data, cb_state, caller_name);
161333f3623e8124c3a6081b60f68b9d39a19a5840aeChris Forbes
161433f3623e8124c3a6081b60f68b9d39a19a5840aeChris Forbes        default:
161533f3623e8124c3a6081b60f68b9d39a19a5840aeChris Forbes            return log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
16169b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                           HandleToUint64(cb_state->commandBuffer), __LINE__, DRAWSTATE_NO_BEGIN_COMMAND_BUFFER, "DS",
161733f3623e8124c3a6081b60f68b9d39a19a5840aeChris Forbes                           "You must call vkBeginCommandBuffer() before this call to %s", caller_name);
16185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
16195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
162029f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis
16217e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis// For given object struct return a ptr of BASE_NODE type for its wrapping struct
16227e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin EhlisBASE_NODE *GetStateStructPtrFromObject(layer_data *dev_data, VK_OBJECT object_struct) {
16237e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis    BASE_NODE *base_ptr = nullptr;
16247e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis    switch (object_struct.type) {
1625ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes        case kVulkanObjectTypeDescriptorSet: {
16269a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            base_ptr = GetSetNode(dev_data, reinterpret_cast<VkDescriptorSet &>(object_struct.handle));
1627cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            break;
1628cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        }
1629ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes        case kVulkanObjectTypeSampler: {
16309a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            base_ptr = GetSamplerState(dev_data, reinterpret_cast<VkSampler &>(object_struct.handle));
1631cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            break;
1632cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        }
1633ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes        case kVulkanObjectTypeQueryPool: {
16349a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            base_ptr = GetQueryPoolNode(dev_data, reinterpret_cast<VkQueryPool &>(object_struct.handle));
1635cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            break;
1636cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        }
1637ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes        case kVulkanObjectTypePipeline: {
1638cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            base_ptr = getPipelineState(dev_data, reinterpret_cast<VkPipeline &>(object_struct.handle));
1639cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            break;
1640cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        }
1641ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes        case kVulkanObjectTypeBuffer: {
16429a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            base_ptr = GetBufferState(dev_data, reinterpret_cast<VkBuffer &>(object_struct.handle));
1643cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            break;
1644cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        }
1645ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes        case kVulkanObjectTypeBufferView: {
16469a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            base_ptr = GetBufferViewState(dev_data, reinterpret_cast<VkBufferView &>(object_struct.handle));
1647cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            break;
1648cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        }
1649ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes        case kVulkanObjectTypeImage: {
16509a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            base_ptr = GetImageState(dev_data, reinterpret_cast<VkImage &>(object_struct.handle));
1651cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            break;
1652cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        }
1653ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes        case kVulkanObjectTypeImageView: {
16549a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            base_ptr = GetImageViewState(dev_data, reinterpret_cast<VkImageView &>(object_struct.handle));
1655cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            break;
1656cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        }
1657ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes        case kVulkanObjectTypeEvent: {
16589a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            base_ptr = GetEventNode(dev_data, reinterpret_cast<VkEvent &>(object_struct.handle));
1659cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            break;
1660cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        }
1661ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes        case kVulkanObjectTypeDescriptorPool: {
16629a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            base_ptr = GetDescriptorPoolState(dev_data, reinterpret_cast<VkDescriptorPool &>(object_struct.handle));
1663cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            break;
1664cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        }
1665ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes        case kVulkanObjectTypeCommandPool: {
16669a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            base_ptr = GetCommandPoolNode(dev_data, reinterpret_cast<VkCommandPool &>(object_struct.handle));
1667cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            break;
1668cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        }
1669ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes        case kVulkanObjectTypeFramebuffer: {
16709a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            base_ptr = GetFramebufferState(dev_data, reinterpret_cast<VkFramebuffer &>(object_struct.handle));
1671cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            break;
1672cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        }
1673ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes        case kVulkanObjectTypeRenderPass: {
16749a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            base_ptr = GetRenderPassState(dev_data, reinterpret_cast<VkRenderPass &>(object_struct.handle));
1675cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            break;
1676cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        }
1677ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes        case kVulkanObjectTypeDeviceMemory: {
16789a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            base_ptr = GetMemObjInfo(dev_data, reinterpret_cast<VkDeviceMemory &>(object_struct.handle));
1679cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            break;
1680cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        }
1681cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        default:
1682cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            // TODO : Any other objects to be handled here?
1683cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            assert(0);
1684cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            break;
1685bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis    }
16867e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis    return base_ptr;
16877e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis}
16887e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis
16897e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis// Tie the VK_OBJECT to the cmd buffer which includes:
16907e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis//  Add object_binding to cmd buffer
16917e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis//  Add cb_binding to object
16927e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlisstatic void addCommandBufferBinding(std::unordered_set<GLOBAL_CB_NODE *> *cb_bindings, VK_OBJECT obj, GLOBAL_CB_NODE *cb_node) {
16937e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis    cb_bindings->insert(cb_node);
16947e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis    cb_node->object_bindings.insert(obj);
16957e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis}
16967e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis// For a given object, if cb_node is in that objects cb_bindings, remove cb_node
16977e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlisstatic void removeCommandBufferBinding(layer_data *dev_data, VK_OBJECT const *object, GLOBAL_CB_NODE *cb_node) {
16987e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis    BASE_NODE *base_obj = GetStateStructPtrFromObject(dev_data, *object);
1699cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (base_obj) base_obj->cb_bindings.erase(cb_node);
1700bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis}
17015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Reset the command buffer state
17025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis//  Maintain the createInfo and set state to CB_NEW, but clear all other state
1703400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlisstatic void resetCB(layer_data *dev_data, const VkCommandBuffer cb) {
1704400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis    GLOBAL_CB_NODE *pCB = dev_data->commandBufferMap[cb];
17055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
1706b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine        pCB->in_use.store(0);
17075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // Reset CB state (note that createInfo is not cleared)
17085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->commandBuffer = cb;
17095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        memset(&pCB->beginInfo, 0, sizeof(VkCommandBufferBeginInfo));
17105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        memset(&pCB->inheritanceInfo, 0, sizeof(VkCommandBufferInheritanceInfo));
1711b68b13ed4952bce61f6ebb0023542660c26b0562Chris Forbes        pCB->hasDrawCmd = false;
17125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->state = CB_NEW;
17135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->submitCount = 0;
17145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->status = 0;
1715b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes        pCB->viewportMask = 0;
1716b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes        pCB->scissorMask = 0;
171793c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski
171872d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis        for (uint32_t i = 0; i < VK_PIPELINE_BIND_POINT_RANGE_SIZE; ++i) {
171972d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis            pCB->lastBound[i].reset();
172072d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis        }
172193c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski
17225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        memset(&pCB->activeRenderPassBeginInfo, 0, sizeof(pCB->activeRenderPassBeginInfo));
1723ee691f5c5fa87aac3750454d2bca2cb582e4e817Chris Forbes        pCB->activeRenderPass = nullptr;
17245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->activeSubpassContents = VK_SUBPASS_CONTENTS_INLINE;
17255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->activeSubpass = 0;
1726e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis        pCB->broken_bindings.clear();
17275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->waitedEvents.clear();
17285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->events.clear();
1729c7e6bc41aa9c6e5a677b138b9459b252cd3bedf2Mark Lobodzinski        pCB->writeEventsBeforeWait.clear();
17305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->waitedEventsBeforeQueryReset.clear();
17315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->queryToStateMap.clear();
17325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->activeQueries.clear();
17335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->startedQueries.clear();
17345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->imageLayoutMap.clear();
17355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->eventToStageMap.clear();
17365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->drawData.clear();
17375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->currentDrawData.buffers.clear();
173858b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis        pCB->vertex_buffer_used = false;
17395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->primaryCommandBuffer = VK_NULL_HANDLE;
17401a3660584634742a3297915c94768d73f360e794Chris Forbes        // If secondary, invalidate any primary command buffer that may call us.
17411a3660584634742a3297915c94768d73f360e794Chris Forbes        if (pCB->createInfo.level == VK_COMMAND_BUFFER_LEVEL_SECONDARY) {
17421a3660584634742a3297915c94768d73f360e794Chris Forbes            invalidateCommandBuffers(dev_data,
17431a3660584634742a3297915c94768d73f360e794Chris Forbes                                     pCB->linkedCommandBuffers,
17441a3660584634742a3297915c94768d73f360e794Chris Forbes                                     {HandleToUint64(cb), kVulkanObjectTypeCommandBuffer});
17451a3660584634742a3297915c94768d73f360e794Chris Forbes        }
17461a3660584634742a3297915c94768d73f360e794Chris Forbes
17471a3660584634742a3297915c94768d73f360e794Chris Forbes        // Remove reverse command buffer links.
17481a3660584634742a3297915c94768d73f360e794Chris Forbes        for (auto pSubCB : pCB->linkedCommandBuffers) {
17491a3660584634742a3297915c94768d73f360e794Chris Forbes            pSubCB->linkedCommandBuffers.erase(pCB);
17501a3660584634742a3297915c94768d73f360e794Chris Forbes        }
17511a3660584634742a3297915c94768d73f360e794Chris Forbes        pCB->linkedCommandBuffers.clear();
17527a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis        pCB->updateImages.clear();
17537a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis        pCB->updateBuffers.clear();
1754400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis        clear_cmd_buf_and_mem_references(dev_data, pCB);
17557974f09e53c82a1d5ae164be83c0b88a92ab8ee5Chris Forbes        pCB->validate_functions.clear();
175679fc00370d55e7cbfd4052b579120e64b0a1a4beTobin Ehlis        pCB->cmd_execute_commands_functions.clear();
1757b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine        pCB->eventUpdates.clear();
1758d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine        pCB->queryUpdates.clear();
175993c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski
1760bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis        // Remove object bindings
1761bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis        for (auto obj : pCB->object_bindings) {
1762bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis            removeCommandBufferBinding(dev_data, &obj, pCB);
1763bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis        }
1764a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis        pCB->object_bindings.clear();
176593c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski        // Remove this cmdBuffer's reference from each FrameBuffer's CB ref list
176693c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski        for (auto framebuffer : pCB->framebuffers) {
17679a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            auto fb_state = GetFramebufferState(dev_data, framebuffer);
1768cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            if (fb_state) fb_state->cb_bindings.erase(pCB);
176993c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski        }
177093c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski        pCB->framebuffers.clear();
17717003b38da5cc27a063af3c45080f3a35438283eeTobin Ehlis        pCB->activeFramebuffer = VK_NULL_HANDLE;
17725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
17735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
17745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
17755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Set PSO-related status bits for CB, including dynamic state set via PSO
17764c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlisstatic void set_cb_pso_status(GLOBAL_CB_NODE *pCB, const PIPELINE_STATE *pPipe) {
17775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Account for any dynamic state not set via this PSO
1778ca546210846c65808717f8875deae39bd227c240Tobin Ehlis    if (!pPipe->graphicsPipelineCI.pDynamicState ||
1779cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        !pPipe->graphicsPipelineCI.pDynamicState->dynamicStateCount) {  // All state is static
17804052946ae557337ff95f3725e879131b1c63f865Tobin Ehlis        pCB->status |= CBSTATUS_ALL_STATE_SET;
17815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    } else {
17825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // First consider all state on
17835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // Then unset any state that's noted as dynamic in PSO
17845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // Finally OR that into CB statemask
17854052946ae557337ff95f3725e879131b1c63f865Tobin Ehlis        CBStatusFlags psoDynStateMask = CBSTATUS_ALL_STATE_SET;
1786ca546210846c65808717f8875deae39bd227c240Tobin Ehlis        for (uint32_t i = 0; i < pPipe->graphicsPipelineCI.pDynamicState->dynamicStateCount; i++) {
1787ca546210846c65808717f8875deae39bd227c240Tobin Ehlis            switch (pPipe->graphicsPipelineCI.pDynamicState->pDynamicStates[i]) {
1788cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                case VK_DYNAMIC_STATE_LINE_WIDTH:
1789cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                    psoDynStateMask &= ~CBSTATUS_LINE_WIDTH_SET;
1790cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                    break;
1791cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                case VK_DYNAMIC_STATE_DEPTH_BIAS:
1792cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                    psoDynStateMask &= ~CBSTATUS_DEPTH_BIAS_SET;
1793cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                    break;
1794cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                case VK_DYNAMIC_STATE_BLEND_CONSTANTS:
1795cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                    psoDynStateMask &= ~CBSTATUS_BLEND_CONSTANTS_SET;
1796cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                    break;
1797cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                case VK_DYNAMIC_STATE_DEPTH_BOUNDS:
1798cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                    psoDynStateMask &= ~CBSTATUS_DEPTH_BOUNDS_SET;
1799cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                    break;
1800cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                case VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK:
1801cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                    psoDynStateMask &= ~CBSTATUS_STENCIL_READ_MASK_SET;
1802cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                    break;
1803cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                case VK_DYNAMIC_STATE_STENCIL_WRITE_MASK:
1804cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                    psoDynStateMask &= ~CBSTATUS_STENCIL_WRITE_MASK_SET;
1805cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                    break;
1806cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                case VK_DYNAMIC_STATE_STENCIL_REFERENCE:
1807cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                    psoDynStateMask &= ~CBSTATUS_STENCIL_REFERENCE_SET;
1808cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                    break;
1809cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                default:
1810cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                    // TODO : Flag error here
1811cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                    break;
18125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
18135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
18145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->status |= psoDynStateMask;
18155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
18165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
18175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
1818623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski// Flags validation error if the associated call is made inside a render pass. The apiName routine should ONLY be called outside a
1819623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski// render pass.
1820e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlisbool insideRenderPass(const layer_data *dev_data, const GLOBAL_CB_NODE *pCB, const char *apiName,
1821e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis                      UNIQUE_VALIDATION_ERROR_CODE msgCode) {
1822e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool inside = false;
18235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB->activeRenderPass) {
182451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis        inside = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
18259b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                         HandleToUint64(pCB->commandBuffer), __LINE__, msgCode, "DS",
1826ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen                         "%s: It is invalid to issue this call inside an active render pass (0x%" PRIxLEAST64 "). %s", apiName,
18279b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                         HandleToUint64(pCB->activeRenderPass->renderPass), validation_error_map[msgCode]);
18285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
18295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return inside;
18305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
18315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
18325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Flags validation error if the associated call is made outside a render pass. The apiName
18335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// routine should ONLY be called inside a render pass.
183451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisbool outsideRenderPass(const layer_data *dev_data, GLOBAL_CB_NODE *pCB, const char *apiName, UNIQUE_VALIDATION_ERROR_CODE msgCode) {
1835e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool outside = false;
18365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (((pCB->createInfo.level == VK_COMMAND_BUFFER_LEVEL_PRIMARY) && (!pCB->activeRenderPass)) ||
18375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        ((pCB->createInfo.level == VK_COMMAND_BUFFER_LEVEL_SECONDARY) && (!pCB->activeRenderPass) &&
18385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis         !(pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT))) {
183951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis        outside = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
18409b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                          HandleToUint64(pCB->commandBuffer), __LINE__, msgCode, "DS",
1841ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen                          "%s: This call must be issued inside an active render pass. %s", apiName, validation_error_map[msgCode]);
18425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
18435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return outside;
18445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
18455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
1846f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbesstatic void init_core_validation(instance_layer_data *instance_data, const VkAllocationCallbacks *pAllocator) {
1847b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis    layer_debug_actions(instance_data->report_data, instance_data->logging_callback, pAllocator, "lunarg_core_validation");
18485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
18495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
18507a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis// For the given ValidationCheck enum, set all relevant instance disabled flags to true
18517a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlisvoid SetDisabledFlags(instance_layer_data *instance_data, VkValidationFlagsEXT *val_flags_struct) {
18527a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis    for (uint32_t i = 0; i < val_flags_struct->disabledValidationCheckCount; ++i) {
18537a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis        switch (val_flags_struct->pDisabledValidationChecks[i]) {
185459ae0ccadec962d9ca2cce7584fad6c57c1a4458Tobin Ehlis            case VK_VALIDATION_CHECK_SHADERS_EXT:
185559ae0ccadec962d9ca2cce7584fad6c57c1a4458Tobin Ehlis                instance_data->disabled.shader_validation = true;
185659ae0ccadec962d9ca2cce7584fad6c57c1a4458Tobin Ehlis                break;
18577a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis            case VK_VALIDATION_CHECK_ALL_EXT:
18587a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis                // Set all disabled flags to true
18597a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis                instance_data->disabled.SetAll(true);
18607a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis                break;
18617a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis            default:
18627a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis                break;
18637a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis        }
18647a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis    }
18657a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis}
18667a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis
1867bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
1868bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                              VkInstance *pInstance) {
18695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
18705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
18715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    assert(chain_info->u.pLayerInfo);
18725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
18735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
1874cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED;
18755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
18765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Advance the link info for the next element on the chain
18775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
18785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
18795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
1880cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (result != VK_SUCCESS) return result;
18815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
188256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(*pInstance), instance_layer_data_map);
188356a5ba3e60a723781945959ffc10e2e215350de5Chia-I Wu    instance_data->instance = *pInstance;
18849172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes    layer_init_instance_dispatch_table(*pInstance, &instance_data->dispatch_table, fpGetInstanceProcAddr);
18859172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes    instance_data->report_data = debug_report_create_instance(
18869172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes        &instance_data->dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount, pCreateInfo->ppEnabledExtensionNames);
18870cf009a4e2a5c22e4645f343c7a998f188a22015Chris Forbes    instance_data->extensions.InitFromInstanceCreateInfo(pCreateInfo);
1888b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis    init_core_validation(instance_data, pAllocator);
1889825ac70f99460ccb9494d34f93d8ee7ec303e5deMark Lobodzinski
18905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    ValidateLayerOrdering(*pCreateInfo);
18917a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis    // Parse any pNext chains
18927a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis    if (pCreateInfo->pNext) {
18937a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis        GENERIC_HEADER *struct_header = (GENERIC_HEADER *)pCreateInfo->pNext;
18947a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis        while (struct_header) {
18957a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis            // Check for VkValidationFlagsExt
18967a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis            if (VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT == struct_header->sType) {
18977a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis                SetDisabledFlags(instance_data, (VkValidationFlagsEXT *)struct_header);
18987a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis            }
18997a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis            struct_header = (GENERIC_HEADER *)struct_header->pNext;
19007a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis        }
19017a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis    }
19025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
19035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
19045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
19055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
190625002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// Hook DestroyInstance to remove tableInstanceMap entry
190789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
19085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // TODOSC : Shouldn't need any customization here
19095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    dispatch_key key = get_dispatch_key(instance);
19105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // TBD: Need any locking this early, in case this function is called at the
19115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // same time by more than one thread?
191256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    instance_layer_data *instance_data = GetLayerDataPtr(key, instance_layer_data_map);
19139172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes    instance_data->dispatch_table.DestroyInstance(instance, pAllocator);
19145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
1915ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    lock_guard_t lock(global_lock);
19165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Clean up logging callback, if any
19179172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes    while (instance_data->logging_callback.size() > 0) {
19189172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes        VkDebugReportCallbackEXT callback = instance_data->logging_callback.back();
19199172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes        layer_destroy_msg_callback(instance_data->report_data, callback, pAllocator);
19209172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes        instance_data->logging_callback.pop_back();
19215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
19225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
19239172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes    layer_debug_report_destroy_instance(instance_data->report_data);
1924d27b109eaf4da0a5514dc2ae2f3dd6a76976ba0dGabríel Arthúr Pétursson    FreeLayerDataPtr(key, instance_layer_data_map);
19255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
19265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
19275770f8ad21c40b2475201e73e9368a899b6886d0Petr Krausstatic bool ValidatePhysicalDeviceQueueFamily(instance_layer_data *instance_data, const PHYSICAL_DEVICE_STATE *pd_state,
19285770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                                              uint32_t requested_queue_family, int32_t err_code, const char *cmd_name,
19295770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                                              const char *queue_family_var_name, const char *vu_note = nullptr) {
19303251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
19315770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
19325770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    if (!vu_note) vu_note = validation_error_map[err_code];
19335770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
19345770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    const char *conditional_ext_cmd =
1935d4eaca34eca7f4b4e34190c441a579347bb2016aMark Lobodzinski        instance_data->extensions.vk_khr_get_physical_device_properties_2 ? "or vkGetPhysicalDeviceQueueFamilyProperties2KHR" : "";
19365770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
19375770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    std::string count_note = (UNCALLED == pd_state->vkGetPhysicalDeviceQueueFamilyPropertiesState)
19385770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                                 ? "the pQueueFamilyPropertyCount was never obtained"
19395770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                                 : "i.e. is not less than " + std::to_string(pd_state->queue_family_count);
19405770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
19415770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    if (requested_queue_family >= pd_state->queue_family_count) {
19423251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
19439b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        HandleToUint64(pd_state->phys_device), __LINE__, err_code, "DL",
19449b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        "%s: %s (= %" PRIu32
19459b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        ") is not less than any previously obtained pQueueFamilyPropertyCount from "
19465770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                        "vkGetPhysicalDeviceQueueFamilyProperties%s (%s). %s",
19475770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                        cmd_name, queue_family_var_name, requested_queue_family, conditional_ext_cmd, count_note.c_str(), vu_note);
19485770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    }
19495770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    return skip;
19505770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus}
19515770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
19525770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus// Verify VkDeviceQueueCreateInfos
19535770f8ad21c40b2475201e73e9368a899b6886d0Petr Krausstatic bool ValidateDeviceQueueCreateInfos(instance_layer_data *instance_data, const PHYSICAL_DEVICE_STATE *pd_state,
19545770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                                           uint32_t info_count, const VkDeviceQueueCreateInfo *infos) {
19555770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    bool skip = false;
19565770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
19575770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    for (uint32_t i = 0; i < info_count; ++i) {
19585770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus        const auto requested_queue_family = infos[i].queueFamilyIndex;
19595770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
19605770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus        // Verify that requested queue family is known to be valid at this point in time
19615770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus        std::string queue_family_var_name = "pCreateInfo->pQueueCreateInfos[" + std::to_string(i) + "].queueFamilyIndex";
1962315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= ValidatePhysicalDeviceQueueFamily(instance_data, pd_state, requested_queue_family, VALIDATION_ERROR_06c002fa,
19635770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                                                  "vkCreateDevice", queue_family_var_name.c_str());
19645770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
19655770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus        // Verify that requested  queue count of queue family is known to be valid at this point in time
19665770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus        if (requested_queue_family < pd_state->queue_family_count) {
19675770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus            const auto requested_queue_count = infos[i].queueCount;
19685770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus            const auto queue_family_props_count = pd_state->queue_family_properties.size();
19695770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus            const bool queue_family_has_props = requested_queue_family < queue_family_props_count;
1970d4eaca34eca7f4b4e34190c441a579347bb2016aMark Lobodzinski            const char *conditional_ext_cmd = instance_data->extensions.vk_khr_get_physical_device_properties_2
19715770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                                                  ? "or vkGetPhysicalDeviceQueueFamilyProperties2KHR"
19725770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                                                  : "";
19735770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus            std::string count_note =
19745770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                !queue_family_has_props
19755770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                    ? "the pQueueFamilyProperties[" + std::to_string(requested_queue_family) + "] was never obtained"
19765770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                    : "i.e. is not less than or equal to " +
19775770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                          std::to_string(pd_state->queue_family_properties[requested_queue_family].queueCount);
19785770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
19795770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus            if (!queue_family_has_props ||
19805770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                requested_queue_count > pd_state->queue_family_properties[requested_queue_family].queueCount) {
19813251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
19829b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, HandleToUint64(pd_state->phys_device), __LINE__,
1983315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                VALIDATION_ERROR_06c002fc, "DL",
19849b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                "vkCreateDevice: pCreateInfo->pQueueCreateInfos[%" PRIu32 "].queueCount (=%" PRIu32
19859b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                ") is not "
19865770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                                "less than or equal to available queue count for this "
19879b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                "pCreateInfo->pQueueCreateInfos[%" PRIu32 "].queueFamilyIndex} (=%" PRIu32
19889b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                ") obtained previously "
19895770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                                "from vkGetPhysicalDeviceQueueFamilyProperties%s (%s). %s",
19905770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                                i, requested_queue_count, i, requested_queue_family, conditional_ext_cmd, count_note.c_str(),
1991315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                validation_error_map[VALIDATION_ERROR_06c002fc]);
1992838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski            }
1993838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski        }
1994838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski    }
19955770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
19963251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
1997838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski}
1998838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski
1999f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski// Verify that features have been queried and that they are available
20005770f8ad21c40b2475201e73e9368a899b6886d0Petr Krausstatic bool ValidateRequestedFeatures(instance_layer_data *instance_data, const PHYSICAL_DEVICE_STATE *pd_state,
2001bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                      const VkPhysicalDeviceFeatures *requested_features) {
20023251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
2003f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski
20045770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    const VkBool32 *actual = reinterpret_cast<const VkBool32 *>(&pd_state->features);
2005825ac70f99460ccb9494d34f93d8ee7ec303e5deMark Lobodzinski    const VkBool32 *requested = reinterpret_cast<const VkBool32 *>(requested_features);
2006f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski    // TODO : This is a nice, compact way to loop through struct, but a bad way to report issues
2007f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski    //  Need to provide the struct member name with the issue. To do that seems like we'll
2008f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski    //  have to loop through each struct member which should be done w/ codegen to keep in synch.
2009f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski    uint32_t errors = 0;
2010f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski    uint32_t total_bools = sizeof(VkPhysicalDeviceFeatures) / sizeof(VkBool32);
2011f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski    for (uint32_t i = 0; i < total_bools; i++) {
2012f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski        if (requested[i] > actual[i]) {
20135770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus            skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
20145770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                            VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_INVALID_FEATURE_REQUESTED, "DL",
201591c2ca58e9ab21299931a4eadf03baf93118242bMark Lobodzinski                            "While calling vkCreateDevice(), requesting feature '%s' in VkPhysicalDeviceFeatures struct, "
20163251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "which is not available on this device.",
201791c2ca58e9ab21299931a4eadf03baf93118242bMark Lobodzinski                            GetPhysDevFeatureString(i));
2018f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski            errors++;
2019f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski        }
2020f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski    }
20215770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    if (errors && (UNCALLED == pd_state->vkGetPhysicalDeviceFeaturesState)) {
2022f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski        // If user didn't request features, notify them that they should
2023f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski        // TODO: Verify this against the spec. I believe this is an invalid use of the API and should return an error
20245770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus        skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
20255770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                        0, __LINE__, DEVLIMITS_INVALID_FEATURE_REQUESTED, "DL",
20263251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "You requested features that are unavailable on this device. You should first query feature "
20273251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "availability by calling vkGetPhysicalDeviceFeatures().");
2028f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski    }
20293251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
2030f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski}
2031f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski
203289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
203389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                            const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
20343251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
20355770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(gpu), instance_layer_data_map);
2036f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
2037ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
2038f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    auto pd_state = GetPhysicalDeviceState(instance_data, gpu);
2039f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
2040f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    // TODO: object_tracker should perhaps do this instead
2041f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    //       and it does not seem to currently work anyway -- the loader just crashes before this point
2042f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    if (!GetPhysicalDeviceState(instance_data, gpu)) {
2043f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus        skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
2044f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus                        0, __LINE__, DEVLIMITS_MUST_QUERY_COUNT, "DL",
2045f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus                        "Invalid call to vkCreateDevice() w/o first calling vkEnumeratePhysicalDevices().");
2046f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    }
2047f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski
2048f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski    // Check that any requested features are available
2049f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski    if (pCreateInfo->pEnabledFeatures) {
20505770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus        skip |= ValidateRequestedFeatures(instance_data, pd_state, pCreateInfo->pEnabledFeatures);
2051f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski    }
20525770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    skip |=
20535770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus        ValidateDeviceQueueCreateInfos(instance_data, pd_state, pCreateInfo->queueCreateInfoCount, pCreateInfo->pQueueCreateInfos);
2054f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski
20555770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
20561d659b4113b77a95325df10d602a03f1e7abf8b7Mark Mueller
20575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
20585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
20595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    assert(chain_info->u.pLayerInfo);
20605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
20615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
206256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_data->instance, "vkCreateDevice");
20635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (fpCreateDevice == NULL) {
20645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return VK_ERROR_INITIALIZATION_FAILED;
20655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
20665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
20675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Advance the link info for the next element on the chain
20685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
20695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
20705770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    lock.unlock();
20715770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
20725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
20735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (result != VK_SUCCESS) {
20745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return result;
20755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
20765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
20775770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    lock.lock();
207856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *device_data = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
20795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
208056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    device_data->instance_data = instance_data;
20815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Setup device dispatch table
208256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_init_device_dispatch_table(*pDevice, &device_data->dispatch_table, fpGetDeviceProcAddr);
208356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    device_data->device = *pDevice;
2084ec85232c4d8d9ddf7d2ae57cb8203c5ab52c1106Mark Lobodzinski    // Save PhysicalDevice handle
208556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    device_data->physical_device = gpu;
20865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
208756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    device_data->report_data = layer_debug_report_create_device(instance_data->report_data, *pDevice);
2088a149f1a0cb39b48b19822c8cf9ef2426cd2251dfMark Lobodzinski    device_data->extensions.InitFromDeviceCreateInfo(&instance_data->extensions, pCreateInfo);
2089d4eaca34eca7f4b4e34190c441a579347bb2016aMark Lobodzinski
20905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Get physical device limits for this device
209156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    instance_data->dispatch_table.GetPhysicalDeviceProperties(gpu, &(device_data->phys_dev_properties.properties));
20925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    uint32_t count;
209356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    instance_data->dispatch_table.GetPhysicalDeviceQueueFamilyProperties(gpu, &count, nullptr);
209456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    device_data->phys_dev_properties.queue_family_properties.resize(count);
209556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    instance_data->dispatch_table.GetPhysicalDeviceQueueFamilyProperties(
209656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis        gpu, &count, &device_data->phys_dev_properties.queue_family_properties[0]);
20975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // TODO: device limits should make sure these are compatible
20985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCreateInfo->pEnabledFeatures) {
209956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis        device_data->enabled_features = *pCreateInfo->pEnabledFeatures;
21005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    } else {
210156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis        memset(&device_data->enabled_features, 0, sizeof(VkPhysicalDeviceFeatures));
21025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
2103e47dbc3f3340fa177d877a67b2adb76a570027e5Mark Lobodzinski    // Store physical device properties and physical device mem limits into device layer_data structs
210456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    instance_data->dispatch_table.GetPhysicalDeviceMemoryProperties(gpu, &device_data->phys_dev_mem_props);
210556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    instance_data->dispatch_table.GetPhysicalDeviceProperties(gpu, &device_data->phys_dev_props);
2106b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
21075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
21085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    ValidateLayerOrdering(*pCreateInfo);
21095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
21105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
21115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
21125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
21135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// prototype
211489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
21155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // TODOSC : Shouldn't need any customization here
21165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    dispatch_key key = get_dispatch_key(device);
211756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(key, layer_data_map);
21185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Free all the memory
2119ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
21205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    deletePipelines(dev_data);
2121fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes    dev_data->renderPassMap.clear();
21229b36ac77fbf55bd7ffdeb9020f2277fff3a5a807Chris Forbes    for (auto ii = dev_data->commandBufferMap.begin(); ii != dev_data->commandBufferMap.end(); ++ii) {
21239b36ac77fbf55bd7ffdeb9020f2277fff3a5a807Chris Forbes        delete (*ii).second;
21249b36ac77fbf55bd7ffdeb9020f2277fff3a5a807Chris Forbes    }
21259b36ac77fbf55bd7ffdeb9020f2277fff3a5a807Chris Forbes    dev_data->commandBufferMap.clear();
2126f13bee0887f3c3d1d597c82869864be3be836737Tobin Ehlis    // This will also delete all sets in the pool & remove them from setMap
21275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    deletePools(dev_data);
2128f13bee0887f3c3d1d597c82869864be3be836737Tobin Ehlis    // All sets should be removed
2129f13bee0887f3c3d1d597c82869864be3be836737Tobin Ehlis    assert(dev_data->setMap.empty());
2130fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis    dev_data->descriptorSetLayoutMap.clear();
21315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    dev_data->imageViewMap.clear();
21325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    dev_data->imageMap.clear();
21335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    dev_data->imageSubresourceMap.clear();
21345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    dev_data->imageLayoutMap.clear();
21355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    dev_data->bufferViewMap.clear();
21365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    dev_data->bufferMap.clear();
21371344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis    // Queues persist until device is destroyed
21381344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis    dev_data->queueMap.clear();
21395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Report any memory leaks
21405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_debug_report_destroy_device(device);
2141b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
21425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
21435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#if DISPATCH_MAP_DEBUG
2144414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller    fprintf(stderr, "Device: 0x%p, key: 0x%p\n", device, key);
21455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#endif
2146d27b109eaf4da0a5514dc2ae2f3dd6a76976ba0dGabríel Arthúr Pétursson
2147d27b109eaf4da0a5514dc2ae2f3dd6a76976ba0dGabríel Arthúr Pétursson    dev_data->dispatch_table.DestroyDevice(device, pAllocator);
2148d27b109eaf4da0a5514dc2ae2f3dd6a76976ba0dGabríel Arthúr Pétursson    FreeLayerDataPtr(key, layer_data_map);
21495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
21505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
21515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
21525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2153208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis// For given stage mask, if Geometry shader stage is on w/o GS being enabled, report geo_error_id
2154208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis//   and if Tessellation Control or Evaluation shader stages are on w/o TS being enabled, report tess_error_id
2155208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlisstatic bool ValidateStageMaskGsTsEnables(layer_data *dev_data, VkPipelineStageFlags stageMask, const char *caller,
2156208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis                                         UNIQUE_VALIDATION_ERROR_CODE geo_error_id, UNIQUE_VALIDATION_ERROR_CODE tess_error_id) {
2157208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis    bool skip = false;
2158208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis    if (!dev_data->enabled_features.geometryShader && (stageMask & VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT)) {
2159208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
2160cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                        geo_error_id, "DL",
2161cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                        "%s call includes a stageMask with VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT bit set when "
2162cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                        "device does not have geometryShader feature enabled. %s",
2163208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis                        caller, validation_error_map[geo_error_id]);
2164208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis    }
2165208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis    if (!dev_data->enabled_features.tessellationShader &&
2166208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis        (stageMask & (VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT | VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT))) {
2167208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
2168cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                        tess_error_id, "DL",
2169cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                        "%s call includes a stageMask with VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT "
2170cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                        "and/or VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT bit(s) set when device "
2171cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                        "does not have tessellationShader feature enabled. %s",
2172208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis                        caller, validation_error_map[tess_error_id]);
2173208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis    }
2174208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis    return skip;
2175208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis}
2176208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis
2177ad97d033b614e6265aaa8c8f0d21a044982d4de7Jeremy Hayes// Loop through bound objects and increment their in_use counts.
2178ad97d033b614e6265aaa8c8f0d21a044982d4de7Jeremy Hayesstatic void IncrementBoundObjects(layer_data *dev_data, GLOBAL_CB_NODE const *cb_node) {
2179a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis    for (auto obj : cb_node->object_bindings) {
2180a317e7593a0fe227635fc8241908471acb36c952Chris Forbes        auto base_obj = GetStateStructPtrFromObject(dev_data, obj);
2181ad97d033b614e6265aaa8c8f0d21a044982d4de7Jeremy Hayes        if (base_obj) {
218251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour            base_obj->in_use.fetch_add(1);
2183162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis        }
2184a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis    }
2185a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis}
21865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Track which resources are in-flight by atomically incrementing their "in_use" count
218751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourstatic void incrementResources(layer_data *dev_data, GLOBAL_CB_NODE *cb_node) {
218851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    cb_node->submitCount++;
21899a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis    cb_node->in_use.fetch_add(1);
2190a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes
2191a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis    // First Increment for all "generic" objects bound to cmd buffer, followed by special-case objects below
2192ad97d033b614e6265aaa8c8f0d21a044982d4de7Jeremy Hayes    IncrementBoundObjects(dev_data, cb_node);
2193a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis    // TODO : We should be able to remove the NULL look-up checks from the code below as long as
2194a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis    //  all the corresponding cases are verified to cause CB_INVALID state and the CB_INVALID state
2195a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis    //  should then be flagged prior to calling this function
21969a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis    for (auto drawDataElement : cb_node->drawData) {
21975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (auto buffer : drawDataElement.buffers) {
21989a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            auto buffer_state = GetBufferState(dev_data, buffer);
219951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour            if (buffer_state) {
22005cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis                buffer_state->in_use.fetch_add(1);
22015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
22025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
22035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
22049a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis    for (auto event : cb_node->writeEventsBeforeWait) {
22059a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto event_state = GetEventNode(dev_data, event);
2206cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        if (event_state) event_state->write_in_use++;
2207c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine    }
22085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
22095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2210b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis// Note: This function assumes that the global lock is held by the calling thread.
2211b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis// For the given queue, verify the queue state up to the given seq number.
2212b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis// Currently the only check is to make sure that if there are events to be waited on prior to
2213b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis//  a QueryReset, make sure that all such events have been signalled.
2214d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbesstatic bool VerifyQueueStateToSeq(layer_data *dev_data, QUEUE_STATE *initial_queue, uint64_t initial_seq) {
2215b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis    bool skip = false;
2216d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes
2217d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes    // sequence number we want to validate up to, per queue
2218d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes    std::unordered_map<QUEUE_STATE *, uint64_t> target_seqs { { initial_queue, initial_seq } };
2219d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes    // sequence number we've completed validation for, per queue
2220d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes    std::unordered_map<QUEUE_STATE *, uint64_t> done_seqs;
2221d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes    std::vector<QUEUE_STATE *> worklist { initial_queue };
2222d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes
2223d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes    while (worklist.size()) {
2224d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes        auto queue = worklist.back();
2225d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes        worklist.pop_back();
2226d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes
2227d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes        auto target_seq = target_seqs[queue];
2228d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes        auto seq = std::max(done_seqs[queue], queue->seq);
2229d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes        auto sub_it = queue->submissions.begin() + int(seq - queue->seq);  // seq >= queue->seq
2230d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes
2231d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes        for (; seq < target_seq; ++sub_it, ++seq) {
2232d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes            for (auto &wait : sub_it->waitSemaphores) {
2233d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes                auto other_queue = GetQueueState(dev_data, wait.queue);
2234d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes
2235d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes                if (other_queue == queue)
2236d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes                    continue;   // semaphores /always/ point backwards, so no point here.
2237d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes
2238d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes                auto other_target_seq = std::max(target_seqs[other_queue], wait.seq);
2239d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes                auto other_done_seq = std::max(done_seqs[other_queue], other_queue->seq);
2240d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes
2241d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes                // if this wait is for another queue, and covers new sequence
2242d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes                // numbers beyond what we've already validated, mark the new
2243d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes                // target seq and (possibly-re)add the queue to the worklist.
2244d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes                if (other_done_seq < other_target_seq) {
2245d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes                    target_seqs[other_queue] = other_target_seq;
2246d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes                    worklist.push_back(other_queue);
2247d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes                }
2248d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes            }
2249d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes
2250d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes            for (auto cb : sub_it->cbs) {
2251d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes                auto cb_node = GetCBNode(dev_data, cb);
2252d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes                if (cb_node) {
2253d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes                    for (auto queryEventsPair : cb_node->waitedEventsBeforeQueryReset) {
2254d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes                        for (auto event : queryEventsPair.second) {
2255d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes                            if (dev_data->eventMap[event].needsSignaled) {
2256d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes                                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
2257d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes                                                VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, 0, DRAWSTATE_INVALID_QUERY, "DS",
2258d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes                                                "Cannot get query results on queryPool 0x%" PRIx64
2259d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes                                                " with index %d which was guarded by unsignaled event 0x%" PRIx64 ".",
22609b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                                HandleToUint64(queryEventsPair.first.pool), queryEventsPair.first.index,
22619b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                                HandleToUint64(event));
2262d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes                            }
2263b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis                        }
2264b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis                    }
2265b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine                }
2266b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine            }
2267b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine        }
2268d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes
2269d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes        // finally mark the point we've now validated this queue to.
2270d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes        done_seqs[queue] = seq;
227192b1701c552e96e96fdbbb77e4b106a9526f3b8cTobin Ehlis    }
2272d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes
2273b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis    return skip;
2274b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis}
2275b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis
2276b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis// When the given fence is retired, verify outstanding queue operations through the point of the fence
2277b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlisstatic bool VerifyQueueStateToFence(layer_data *dev_data, VkFence fence) {
22789a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto fence_state = GetFenceNode(dev_data, fence);
2279b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis    if (VK_NULL_HANDLE != fence_state->signaler.first) {
22809a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        return VerifyQueueStateToSeq(dev_data, GetQueueState(dev_data, fence_state->signaler.first), fence_state->signaler.second);
2281b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis    }
2282b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis    return false;
2283b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine}
22847d33205c3aa4aba751a2c07f956634aac616f916Chris Forbes
2285a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis// Decrement in-use count for objects bound to command buffer
22862f8cbf3b166e175174877a59929902e005953d6dTobin Ehlisstatic void DecrementBoundResources(layer_data *dev_data, GLOBAL_CB_NODE const *cb_node) {
228700e8ce2e6c1c191758f7b7c15eeaf350e5b4a3b6Tobin Ehlis    BASE_NODE *base_obj = nullptr;
2288a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis    for (auto obj : cb_node->object_bindings) {
22897e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        base_obj = GetStateStructPtrFromObject(dev_data, obj);
229000e8ce2e6c1c191758f7b7c15eeaf350e5b4a3b6Tobin Ehlis        if (base_obj) {
229100e8ce2e6c1c191758f7b7c15eeaf350e5b4a3b6Tobin Ehlis            base_obj->in_use.fetch_sub(1);
229200e8ce2e6c1c191758f7b7c15eeaf350e5b4a3b6Tobin Ehlis        }
2293a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis    }
2294a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis}
2295da8f07baf262972eb3e719fa07b073c180dff157Chris Forbes
229636c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlisstatic void RetireWorkOnQueue(layer_data *dev_data, QUEUE_STATE *pQueue, uint64_t seq) {
22979867daedbf52debc77d6568162ee21e071699b80Chris Forbes    std::unordered_map<VkQueue, uint64_t> otherQueueSeqs;
22989867daedbf52debc77d6568162ee21e071699b80Chris Forbes
22999867daedbf52debc77d6568162ee21e071699b80Chris Forbes    // Roll this queue forward, one submission at a time.
23009867daedbf52debc77d6568162ee21e071699b80Chris Forbes    while (pQueue->seq < seq) {
2301bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        auto &submission = pQueue->submissions.front();
23029867daedbf52debc77d6568162ee21e071699b80Chris Forbes
2303bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        for (auto &wait : submission.waitSemaphores) {
23049a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            auto pSemaphore = GetSemaphoreNode(dev_data, wait.semaphore);
2305c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski            if (pSemaphore) {
2306c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski                pSemaphore->in_use.fetch_sub(1);
2307c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski            }
2308bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski            auto &lastSeq = otherQueueSeqs[wait.queue];
23099867daedbf52debc77d6568162ee21e071699b80Chris Forbes            lastSeq = std::max(lastSeq, wait.seq);
2310da8f07baf262972eb3e719fa07b073c180dff157Chris Forbes        }
2311cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes
2312bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        for (auto &semaphore : submission.signalSemaphores) {
23139a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            auto pSemaphore = GetSemaphoreNode(dev_data, semaphore);
2314c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski            if (pSemaphore) {
2315c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski                pSemaphore->in_use.fetch_sub(1);
2316c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski            }
23179867daedbf52debc77d6568162ee21e071699b80Chris Forbes        }
2318cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes
23199867daedbf52debc77d6568162ee21e071699b80Chris Forbes        for (auto cb : submission.cbs) {
23209a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            auto cb_node = GetCBNode(dev_data, cb);
2321c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski            if (!cb_node) {
2322c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski                continue;
2323c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski            }
2324a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis            // First perform decrement on general case bound objects
23259a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis            DecrementBoundResources(dev_data, cb_node);
23269a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis            for (auto drawDataElement : cb_node->drawData) {
23279867daedbf52debc77d6568162ee21e071699b80Chris Forbes                for (auto buffer : drawDataElement.buffers) {
23289a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                    auto buffer_state = GetBufferState(dev_data, buffer);
23295cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis                    if (buffer_state) {
23305cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis                        buffer_state->in_use.fetch_sub(1);
23319867daedbf52debc77d6568162ee21e071699b80Chris Forbes                    }
23329867daedbf52debc77d6568162ee21e071699b80Chris Forbes                }
2333da8f07baf262972eb3e719fa07b073c180dff157Chris Forbes            }
23349a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis            for (auto event : cb_node->writeEventsBeforeWait) {
23359867daedbf52debc77d6568162ee21e071699b80Chris Forbes                auto eventNode = dev_data->eventMap.find(event);
23369867daedbf52debc77d6568162ee21e071699b80Chris Forbes                if (eventNode != dev_data->eventMap.end()) {
23379867daedbf52debc77d6568162ee21e071699b80Chris Forbes                    eventNode->second.write_in_use--;
23389867daedbf52debc77d6568162ee21e071699b80Chris Forbes                }
23399867daedbf52debc77d6568162ee21e071699b80Chris Forbes            }
23409a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis            for (auto queryStatePair : cb_node->queryToStateMap) {
23419867daedbf52debc77d6568162ee21e071699b80Chris Forbes                dev_data->queryToStateMap[queryStatePair.first] = queryStatePair.second;
23429867daedbf52debc77d6568162ee21e071699b80Chris Forbes            }
23439a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis            for (auto eventStagePair : cb_node->eventToStageMap) {
23449867daedbf52debc77d6568162ee21e071699b80Chris Forbes                dev_data->eventMap[eventStagePair.first].stageMask = eventStagePair.second;
2345da8f07baf262972eb3e719fa07b073c180dff157Chris Forbes            }
23460a32ed7bdf03e7bda914e03c0bfa6ebf400cdf5bMichael Lentine
2347a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes            cb_node->in_use.fetch_sub(1);
23480a32ed7bdf03e7bda914e03c0bfa6ebf400cdf5bMichael Lentine        }
23499867daedbf52debc77d6568162ee21e071699b80Chris Forbes
23509a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto pFence = GetFenceNode(dev_data, submission.fence);
23519867daedbf52debc77d6568162ee21e071699b80Chris Forbes        if (pFence) {
23529867daedbf52debc77d6568162ee21e071699b80Chris Forbes            pFence->state = FENCE_RETIRED;
23530a32ed7bdf03e7bda914e03c0bfa6ebf400cdf5bMichael Lentine        }
23549867daedbf52debc77d6568162ee21e071699b80Chris Forbes
23559867daedbf52debc77d6568162ee21e071699b80Chris Forbes        pQueue->submissions.pop_front();
23569867daedbf52debc77d6568162ee21e071699b80Chris Forbes        pQueue->seq++;
2357b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine    }
23589867daedbf52debc77d6568162ee21e071699b80Chris Forbes
23599867daedbf52debc77d6568162ee21e071699b80Chris Forbes    // Roll other queues forward to the highest seq we saw a wait for
23609867daedbf52debc77d6568162ee21e071699b80Chris Forbes    for (auto qs : otherQueueSeqs) {
23619a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        RetireWorkOnQueue(dev_data, GetQueueState(dev_data, qs.first), qs.second);
2362d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine    }
23639867daedbf52debc77d6568162ee21e071699b80Chris Forbes}
2364651d92815dfff917308137bb67aacccc4f60df86Chris Forbes
2365651d92815dfff917308137bb67aacccc4f60df86Chris Forbes// Submit a fence to a queue, delimiting previous fences and previous untracked
2366651d92815dfff917308137bb67aacccc4f60df86Chris Forbes// work by it.
236736c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlisstatic void SubmitFence(QUEUE_STATE *pQueue, FENCE_NODE *pFence, uint64_t submitCount) {
2368cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes    pFence->state = FENCE_INFLIGHT;
23699867daedbf52debc77d6568162ee21e071699b80Chris Forbes    pFence->signaler.first = pQueue->queue;
23709867daedbf52debc77d6568162ee21e071699b80Chris Forbes    pFence->signaler.second = pQueue->seq + pQueue->submissions.size() + submitCount;
2371b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine}
2372b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine
237351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourstatic bool validateCommandBufferSimultaneousUse(layer_data *dev_data, GLOBAL_CB_NODE *pCB, int current_submit_count) {
23743251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
2375a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes    if ((pCB->in_use.load() || current_submit_count > 1) &&
23765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        !(pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT)) {
23773251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0,
2378315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        __LINE__, VALIDATION_ERROR_31a0008e, "DS",
23793251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "Command Buffer 0x%p is already in use and is not marked for simultaneous use. %s", pCB->commandBuffer,
2380315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_31a0008e]);
23815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
23823251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
23835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
23845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2385946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinskistatic bool validateCommandBufferState(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, const char *call_source,
23860de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                                       int current_submit_count, UNIQUE_VALIDATION_ERROR_CODE vu_id) {
2387c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis    bool skip = false;
2388cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.command_buffer_state) return skip;
23890a59acde4b40fde3bbfea5811d2abf2c85ca62f4Tobin Ehlis    // Validate ONE_TIME_SUBMIT_BIT CB is not being submitted more than once
2390946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski    if ((cb_state->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT) &&
2391946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski        (cb_state->submitCount + current_submit_count > 1)) {
2392c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0,
2393c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis                        __LINE__, DRAWSTATE_COMMAND_BUFFER_SINGLE_SUBMIT_VIOLATION, "DS",
2394226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis                        "Commandbuffer 0x%p was begun w/ VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT "
2395c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis                        "set, but has been submitted 0x%" PRIxLEAST64 " times.",
2396946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski                        cb_state->commandBuffer, cb_state->submitCount + current_submit_count);
23970a59acde4b40fde3bbfea5811d2abf2c85ca62f4Tobin Ehlis    }
239894307efee520ad91d5da2ff8f40609b31f05b2efChris Forbes
23995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Validate that cmd buffers have been updated
240046daa701a01b92ae19e3ee9e661d677128fe7e6dChris Forbes    switch (cb_state->state) {
240146daa701a01b92ae19e3ee9e661d677128fe7e6dChris Forbes        case CB_INVALID_INCOMPLETE:
240246daa701a01b92ae19e3ee9e661d677128fe7e6dChris Forbes        case CB_INVALID_COMPLETE:
2403946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski            skip |= ReportInvalidCommandBuffer(dev_data, cb_state, call_source);
240446daa701a01b92ae19e3ee9e661d677128fe7e6dChris Forbes            break;
240546daa701a01b92ae19e3ee9e661d677128fe7e6dChris Forbes
240646daa701a01b92ae19e3ee9e661d677128fe7e6dChris Forbes        case CB_NEW:
24070de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
24080de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                            (uint64_t)(cb_state->commandBuffer), __LINE__, vu_id, "DS",
24090de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                            "Command buffer 0x%p used in the call to %s is unrecorded and contains no commands. %s",
24100de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                            cb_state->commandBuffer, call_source, validation_error_map[vu_id]);
241146daa701a01b92ae19e3ee9e661d677128fe7e6dChris Forbes            break;
241246daa701a01b92ae19e3ee9e661d677128fe7e6dChris Forbes
241346daa701a01b92ae19e3ee9e661d677128fe7e6dChris Forbes        case CB_RECORDING:
2414c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
24159b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(cb_state->commandBuffer), __LINE__, DRAWSTATE_NO_END_COMMAND_BUFFER, "DS",
2416946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski                            "You must call vkEndCommandBuffer() on command buffer 0x%p before this call to %s!",
2417946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski                            cb_state->commandBuffer, call_source);
241846daa701a01b92ae19e3ee9e661d677128fe7e6dChris Forbes            break;
241946daa701a01b92ae19e3ee9e661d677128fe7e6dChris Forbes
242046daa701a01b92ae19e3ee9e661d677128fe7e6dChris Forbes        default: /* recorded */
242146daa701a01b92ae19e3ee9e661d677128fe7e6dChris Forbes            break;
24225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
2423c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis    return skip;
24245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
24255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
242651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourstatic bool validateResources(layer_data *dev_data, GLOBAL_CB_NODE *cb_node) {
24273251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
242851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour
242951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    // TODO : We should be able to remove the NULL look-up checks from the code below as long as
243051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    //  all the corresponding cases are verified to cause CB_INVALID state and the CB_INVALID state
243151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    //  should then be flagged prior to calling this function
243251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    for (auto drawDataElement : cb_node->drawData) {
243351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour        for (auto buffer : drawDataElement.buffers) {
243451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour            auto buffer_state = GetBufferState(dev_data, buffer);
243551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour            if (!buffer_state) {
24363251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT,
24379b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                HandleToUint64(buffer), __LINE__, DRAWSTATE_INVALID_BUFFER, "DS",
24389b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                "Cannot submit cmd buffer using deleted buffer 0x%" PRIx64 ".", HandleToUint64(buffer));
243951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour            }
244051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour        }
244151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    }
24423251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
244351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour}
244451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour
2445f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski// Check that the queue family index of 'queue' matches one of the entries in pQueueFamilyIndices
2446f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinskibool ValidImageBufferQueue(layer_data *dev_data, GLOBAL_CB_NODE *cb_node, const VK_OBJECT *object, VkQueue queue, uint32_t count,
2447f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski                           const uint32_t *indices) {
2448f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski    bool found = false;
2449f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski    bool skip = false;
2450f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski    auto queue_state = GetQueueState(dev_data, queue);
2451f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski    if (queue_state) {
2452f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski        for (uint32_t i = 0; i < count; i++) {
2453f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski            if (indices[i] == queue_state->queueFamilyIndex) {
2454f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski                found = true;
2455f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski                break;
2456f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski            }
2457f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski        }
2458f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski
2459f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski        if (!found) {
24609b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus            skip = log_msg(
24619b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, get_debug_report_enum[object->type], object->handle, __LINE__,
24629b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                DRAWSTATE_INVALID_QUEUE_FAMILY, "DS", "vkQueueSubmit: Command buffer 0x%" PRIxLEAST64 " contains %s 0x%" PRIxLEAST64
24639b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                                      " which was not created allowing concurrent access to this queue family %d.",
24649b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                HandleToUint64(cb_node->commandBuffer), object_string[object->type], object->handle, queue_state->queueFamilyIndex);
2465f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski        }
2466f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski    }
2467f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski    return skip;
2468f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski}
2469f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski
24707bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski// Validate that queueFamilyIndices of primary command buffers match this queue
24717bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski// Secondary command buffers were previously validated in vkCmdExecuteCommands().
24727bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinskistatic bool validateQueueFamilyIndices(layer_data *dev_data, GLOBAL_CB_NODE *pCB, VkQueue queue) {
24733251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
24749a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto pPool = GetCommandPoolNode(dev_data, pCB->createInfo.commandPool);
24759a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto queue_state = GetQueueState(dev_data, queue);
24767bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski
2477f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski    if (pPool && queue_state) {
2478f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski        if (pPool->queueFamilyIndex != queue_state->queueFamilyIndex) {
24793251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
2480315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(pCB->commandBuffer), __LINE__, VALIDATION_ERROR_31a00094, "DS",
24813251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "vkQueueSubmit: Primary command buffer 0x%p created in queue family %d is being submitted on queue "
24823251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "0x%p from queue family %d. %s",
24833251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            pCB->commandBuffer, pPool->queueFamilyIndex, queue, queue_state->queueFamilyIndex,
2484315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            validation_error_map[VALIDATION_ERROR_31a00094]);
2485f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski        }
2486f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski
2487f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski        // Ensure that any bound images or buffers created with SHARING_MODE_CONCURRENT have access to the current queue family
2488f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski        for (auto object : pCB->object_bindings) {
24897a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski            if (object.type == kVulkanObjectTypeImage) {
2490f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski                auto image_state = GetImageState(dev_data, reinterpret_cast<VkImage &>(object.handle));
2491f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski                if (image_state && image_state->createInfo.sharingMode == VK_SHARING_MODE_CONCURRENT) {
24923251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= ValidImageBufferQueue(dev_data, pCB, &object, queue, image_state->createInfo.queueFamilyIndexCount,
24933251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                                  image_state->createInfo.pQueueFamilyIndices);
2494f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski                }
24957a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski            } else if (object.type == kVulkanObjectTypeBuffer) {
2496f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski                auto buffer_state = GetBufferState(dev_data, reinterpret_cast<VkBuffer &>(object.handle));
2497f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski                if (buffer_state && buffer_state->createInfo.sharingMode == VK_SHARING_MODE_CONCURRENT) {
24983251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= ValidImageBufferQueue(dev_data, pCB, &object, queue, buffer_state->createInfo.queueFamilyIndexCount,
24993251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                                  buffer_state->createInfo.pQueueFamilyIndices);
2500f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski                }
2501f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski            }
2502f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski        }
25037bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski    }
25047bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski
25053251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
25067bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski}
25077bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski
250851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourstatic bool validatePrimaryCommandBufferState(layer_data *dev_data, GLOBAL_CB_NODE *pCB, int current_submit_count) {
25095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Track in-use for resources off of primary and any secondary CBs
25103251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
2511a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes
2512a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes    // If USAGE_SIMULTANEOUS_USE_BIT not set then CB cannot already be executing
2513a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes    // on device
25143251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    skip |= validateCommandBufferSimultaneousUse(dev_data, pCB, current_submit_count);
2515a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes
25163251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    skip |= validateResources(dev_data, pCB);
2517a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes
25181a3660584634742a3297915c94768d73f360e794Chris Forbes    for (auto pSubCB : pCB->linkedCommandBuffers) {
251911decd82041d4b10aac41360fc76b6fda4f4bd27Chris Forbes        skip |= validateResources(dev_data, pSubCB);
25201a3660584634742a3297915c94768d73f360e794Chris Forbes        // TODO: replace with invalidateCommandBuffers() at recording.
252111decd82041d4b10aac41360fc76b6fda4f4bd27Chris Forbes        if ((pSubCB->primaryCommandBuffer != pCB->commandBuffer) &&
252211decd82041d4b10aac41360fc76b6fda4f4bd27Chris Forbes            !(pSubCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT)) {
2523315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis            log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0,
2524315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                    __LINE__, VALIDATION_ERROR_31a00092, "DS",
2525315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                    "Commandbuffer 0x%p was submitted with secondary buffer 0x%p but that buffer has subsequently been bound to "
2526f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen                    "primary cmd buffer 0x%p and it does not have VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT set. %s",
2527315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                    pCB->commandBuffer, pSubCB->commandBuffer, pSubCB->primaryCommandBuffer,
2528315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                    validation_error_map[VALIDATION_ERROR_31a00092]);
25295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
25305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
2531a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes
2532315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis    skip |= validateCommandBufferState(dev_data, pCB, "vkQueueSubmit()", current_submit_count, VALIDATION_ERROR_31a00090);
2533a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes
25343251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
25355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
25365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2537bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic bool ValidateFenceForSubmit(layer_data *dev_data, FENCE_NODE *pFence) {
25383251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
253981c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes
2540651d92815dfff917308137bb67aacccc4f60df86Chris Forbes    if (pFence) {
2541cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes        if (pFence->state == FENCE_INFLIGHT) {
2542315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis            // TODO: opportunities for VALIDATION_ERROR_31a00080, VALIDATION_ERROR_316008b4, VALIDATION_ERROR_16400a0e
25433251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT,
25449b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(pFence->fence), __LINE__, DRAWSTATE_INVALID_FENCE, "DS",
25459b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            "Fence 0x%" PRIx64 " is already in use by another submission.", HandleToUint64(pFence->fence));
2546a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis        }
254781c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes
2548cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes        else if (pFence->state == FENCE_RETIRED) {
2549315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis            // TODO: opportunities for VALIDATION_ERROR_31a0007e, VALIDATION_ERROR_316008b2, VALIDATION_ERROR_16400a0e
25503251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT,
25519b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(pFence->fence), __LINE__, MEMTRACK_INVALID_FENCE_STATE, "MEM",
25523251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "Fence 0x%" PRIxLEAST64 " submitted in SIGNALED state.  Fences must be reset before being submitted",
25539b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(pFence->fence));
2554a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis        }
25555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
255681c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes
25573251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
255881c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes}
255981c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes
256051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourstatic void PostCallRecordQueueSubmit(layer_data *dev_data, VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits,
256151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                                      VkFence fence) {
25629a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto pQueue = GetQueueState(dev_data, queue);
25639a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto pFence = GetFenceNode(dev_data, fence);
2564d7d60cccc862fee2d0b3ad410c5fdcc40ddc83aeChris Forbes
2565651d92815dfff917308137bb67aacccc4f60df86Chris Forbes    // Mark the fence in-use.
2566651d92815dfff917308137bb67aacccc4f60df86Chris Forbes    if (pFence) {
25679867daedbf52debc77d6568162ee21e071699b80Chris Forbes        SubmitFence(pQueue, pFence, std::max(1u, submitCount));
2568651d92815dfff917308137bb67aacccc4f60df86Chris Forbes    }
2569651d92815dfff917308137bb67aacccc4f60df86Chris Forbes
257051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    // Now process each individual submit
25715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
257251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour        std::vector<VkCommandBuffer> cbs;
25735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        const VkSubmitInfo *submit = &pSubmits[submit_idx];
25749867daedbf52debc77d6568162ee21e071699b80Chris Forbes        vector<SEMAPHORE_WAIT> semaphore_waits;
25759867daedbf52debc77d6568162ee21e071699b80Chris Forbes        vector<VkSemaphore> semaphore_signals;
25765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t i = 0; i < submit->waitSemaphoreCount; ++i) {
257751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour            VkSemaphore semaphore = submit->pWaitSemaphores[i];
257851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour            auto pSemaphore = GetSemaphoreNode(dev_data, semaphore);
257951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour            if (pSemaphore) {
258051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                if (pSemaphore->signaler.first != VK_NULL_HANDLE) {
258151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                    semaphore_waits.push_back({semaphore, pSemaphore->signaler.first, pSemaphore->signaler.second});
258251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                    pSemaphore->in_use.fetch_add(1);
258351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                }
258451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                pSemaphore->signaler.first = VK_NULL_HANDLE;
258551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                pSemaphore->signaled = false;
258651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour            }
258751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour        }
258851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour        for (uint32_t i = 0; i < submit->signalSemaphoreCount; ++i) {
258951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour            VkSemaphore semaphore = submit->pSignalSemaphores[i];
259051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour            auto pSemaphore = GetSemaphoreNode(dev_data, semaphore);
259151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour            if (pSemaphore) {
259251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                pSemaphore->signaler.first = queue;
259351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                pSemaphore->signaler.second = pQueue->seq + pQueue->submissions.size() + 1;
259451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                pSemaphore->signaled = true;
259551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                pSemaphore->in_use.fetch_add(1);
259651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                semaphore_signals.push_back(semaphore);
259751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour            }
259851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour        }
259951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour        for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
260051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour            auto cb_node = GetCBNode(dev_data, submit->pCommandBuffers[i]);
260151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour            if (cb_node) {
260251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                cbs.push_back(submit->pCommandBuffers[i]);
26031a3660584634742a3297915c94768d73f360e794Chris Forbes                for (auto secondaryCmdBuffer : cb_node->linkedCommandBuffers) {
260411decd82041d4b10aac41360fc76b6fda4f4bd27Chris Forbes                    cbs.push_back(secondaryCmdBuffer->commandBuffer);
260551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                }
260651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                UpdateCmdBufImageLayouts(dev_data, cb_node);
260751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                incrementResources(dev_data, cb_node);
26081a3660584634742a3297915c94768d73f360e794Chris Forbes                for (auto secondaryCmdBuffer : cb_node->linkedCommandBuffers) {
260911decd82041d4b10aac41360fc76b6fda4f4bd27Chris Forbes                    incrementResources(dev_data, secondaryCmdBuffer);
261051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                }
261151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour            }
261251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour        }
261351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour        pQueue->submissions.emplace_back(cbs, semaphore_waits, semaphore_signals,
261451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                                         submit_idx == submitCount - 1 ? fence : VK_NULL_HANDLE);
261551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    }
261651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour
261751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    if (pFence && !submitCount) {
261851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour        // If no submissions, but just dropping a fence on the end of the queue,
261951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour        // record an empty submission with just the fence, so we can determine
262051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour        // its completion.
262151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour        pQueue->submissions.emplace_back(std::vector<VkCommandBuffer>(), std::vector<SEMAPHORE_WAIT>(), std::vector<VkSemaphore>(),
262251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                                         fence);
262351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    }
262451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour}
262551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour
262651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourstatic bool PreCallValidateQueueSubmit(layer_data *dev_data, VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits,
262751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                                       VkFence fence) {
262851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    auto pFence = GetFenceNode(dev_data, fence);
26293251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = ValidateFenceForSubmit(dev_data, pFence);
26303251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (skip) {
263151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour        return true;
263251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    }
263351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour
263451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    unordered_set<VkSemaphore> signaled_semaphores;
263551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    unordered_set<VkSemaphore> unsignaled_semaphores;
263651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    vector<VkCommandBuffer> current_cmds;
2637c25ac48846c975d698243e53750c6bca28bba33eChris Forbes    unordered_map<ImageSubresourcePair, IMAGE_LAYOUT_NODE> localImageLayoutMap;
263851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    // Now verify each individual submit
263951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
264051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour        const VkSubmitInfo *submit = &pSubmits[submit_idx];
264151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour        for (uint32_t i = 0; i < submit->waitSemaphoreCount; ++i) {
2642315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis            skip |= ValidateStageMaskGsTsEnables(dev_data, submit->pWaitDstStageMask[i], "vkQueueSubmit()",
2643315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                                 VALIDATION_ERROR_13c00098, VALIDATION_ERROR_13c0009a);
264401a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes            VkSemaphore semaphore = submit->pWaitSemaphores[i];
26459a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            auto pSemaphore = GetSemaphoreNode(dev_data, semaphore);
264601a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes            if (pSemaphore) {
264751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                if (unsignaled_semaphores.count(semaphore) ||
2648440bdd357701497c3442e3515f12ac1cfffc180aTony Barbour                    (!(signaled_semaphores.count(semaphore)) && !(pSemaphore->signaled))) {
26493251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT,
26509b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                    HandleToUint64(semaphore), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS",
26513251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    "Queue 0x%p is waiting on semaphore 0x%" PRIx64 " that has no way to be signaled.", queue,
26529b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                    HandleToUint64(semaphore));
265351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                } else {
265451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                    signaled_semaphores.erase(semaphore);
265551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                    unsignaled_semaphores.insert(semaphore);
26561344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis                }
26575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
26585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
26595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t i = 0; i < submit->signalSemaphoreCount; ++i) {
266001a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes            VkSemaphore semaphore = submit->pSignalSemaphores[i];
26619a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            auto pSemaphore = GetSemaphoreNode(dev_data, semaphore);
266201a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes            if (pSemaphore) {
2663440bdd357701497c3442e3515f12ac1cfffc180aTony Barbour                if (signaled_semaphores.count(semaphore) || (!(unsignaled_semaphores.count(semaphore)) && pSemaphore->signaled)) {
26643251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT,
26659b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                    HandleToUint64(semaphore), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS",
26663251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    "Queue 0x%p is signaling semaphore 0x%" PRIx64
26673251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    " that has already been signaled but not waited on by queue 0x%" PRIx64 ".",
26689b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                    queue, HandleToUint64(semaphore), HandleToUint64(pSemaphore->signaler.first));
26691344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis                } else {
267051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                    unsignaled_semaphores.erase(semaphore);
267151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                    signaled_semaphores.insert(semaphore);
26721344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis                }
26730a32ed7bdf03e7bda914e03c0bfa6ebf400cdf5bMichael Lentine            }
26745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
26755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
26769a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            auto cb_node = GetCBNode(dev_data, submit->pCommandBuffers[i]);
2677d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis            if (cb_node) {
2678c25ac48846c975d698243e53750c6bca28bba33eChris Forbes                skip |= ValidateCmdBufImageLayouts(dev_data, cb_node, dev_data->imageLayoutMap, localImageLayoutMap);
267951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                current_cmds.push_back(submit->pCommandBuffers[i]);
26803251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= validatePrimaryCommandBufferState(
268151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                    dev_data, cb_node, (int)std::count(current_cmds.begin(), current_cmds.end(), submit->pCommandBuffers[i]));
26823251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= validateQueueFamilyIndices(dev_data, cb_node, queue);
268351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour
2684ea371fa7c8c57edb4d1436e4570cf54f3fc0463fTobin Ehlis                // Potential early exit here as bad object state may crash in delayed function calls
26853251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                if (skip) {
268651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                    return true;
268751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                }
268851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour
26891344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis                // Call submit-time functions to validate/update state
2690d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis                for (auto &function : cb_node->validate_functions) {
26913251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= function();
26921344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis                }
2693d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis                for (auto &function : cb_node->eventUpdates) {
26943251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= function(queue);
26951344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis                }
2696d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis                for (auto &function : cb_node->queryUpdates) {
26973251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= function(queue);
2698d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine                }
26991344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis            }
27005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
27019867daedbf52debc77d6568162ee21e071699b80Chris Forbes    }
27023251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
270351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour}
27049867daedbf52debc77d6568162ee21e071699b80Chris Forbes
270551920949f887ce8d3666c73c28ff19a5d8325a37Tony BarbourVKAPI_ATTR VkResult VKAPI_CALL QueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence) {
270651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map);
2707ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
270851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour
270951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    bool skip = PreCallValidateQueueSubmit(dev_data, queue, submitCount, pSubmits, fence);
2710b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
27115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2712440bdd357701497c3442e3515f12ac1cfffc180aTony Barbour    if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
271351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour
271451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    VkResult result = dev_data->dispatch_table.QueueSubmit(queue, submitCount, pSubmits, fence);
271551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour
271651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    lock.lock();
271751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    PostCallRecordQueueSubmit(dev_data, queue, submitCount, pSubmits, fence);
271851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    lock.unlock();
27195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
27205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
27215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2722f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultzstatic bool PreCallValidateAllocateMemory(layer_data *dev_data) {
2723f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz    bool skip = false;
2724f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz    if (dev_data->memObjMap.size() >= dev_data->phys_dev_properties.properties.limits.maxMemoryAllocationCount) {
2725f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
2726315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(dev_data->device), __LINE__, VALIDATION_ERROR_16c004f8, "MEM",
2727f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz                        "Number of currently valid memory objects is not less than the maximum allowed (%u). %s",
2728f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz                        dev_data->phys_dev_properties.properties.limits.maxMemoryAllocationCount,
2729315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_16c004f8]);
2730f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz    }
2731f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz    return skip;
2732f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz}
2733f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz
2734f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultzstatic void PostCallRecordAllocateMemory(layer_data *dev_data, const VkMemoryAllocateInfo *pAllocateInfo, VkDeviceMemory *pMemory) {
2735f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz    add_mem_obj_info(dev_data, dev_data->device, *pMemory, pAllocateInfo);
2736f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz    return;
2737f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz}
2738f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz
273989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL AllocateMemory(VkDevice device, const VkMemoryAllocateInfo *pAllocateInfo,
274089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                              const VkAllocationCallbacks *pAllocator, VkDeviceMemory *pMemory) {
2741f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
274256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
2743ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
2744f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz    bool skip = PreCallValidateAllocateMemory(dev_data);
2745f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz    if (!skip) {
2746f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz        lock.unlock();
2747f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz        result = dev_data->dispatch_table.AllocateMemory(device, pAllocateInfo, pAllocator, pMemory);
2748f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz        lock.lock();
2749f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz        if (VK_SUCCESS == result) {
2750f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz            PostCallRecordAllocateMemory(dev_data, pAllocateInfo, pMemory);
2751f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz        }
2752e12739a56d02ca2fb5f0273862668e7475a21a6cMark Lobodzinski    }
27535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
27545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
27555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2756177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis// For given obj node, if it is use, flag a validation error and return callback result, else return false
2757177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlisbool ValidateObjectNotInUse(const layer_data *dev_data, BASE_NODE *obj_node, VK_OBJECT obj_struct,
2758177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis                            UNIQUE_VALIDATION_ERROR_CODE error_code) {
2759cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.object_in_use) return false;
2760177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis    bool skip = false;
2761177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis    if (obj_node->in_use.load()) {
27627a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski        skip |=
276302a510945ff39f3d9e486e456aca5bfa6ea0c43aMark Lobodzinski            log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, get_debug_report_enum[obj_struct.type], obj_struct.handle,
27647a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski                    __LINE__, error_code, "DS", "Cannot delete %s 0x%" PRIx64 " that is currently in use by a command buffer. %s",
27657a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski                    object_string[obj_struct.type], obj_struct.handle, validation_error_map[error_code]);
2766177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis    }
2767177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis    return skip;
2768177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis}
27695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2770177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlisstatic bool PreCallValidateFreeMemory(layer_data *dev_data, VkDeviceMemory mem, DEVICE_MEM_INFO **mem_info, VK_OBJECT *obj_struct) {
27719a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    *mem_info = GetMemObjInfo(dev_data, mem);
27729b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus    *obj_struct = {HandleToUint64(mem), kVulkanObjectTypeDeviceMemory};
2773cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.free_memory) return false;
2774177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis    bool skip = false;
2775177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis    if (*mem_info) {
2776315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= ValidateObjectNotInUse(dev_data, *mem_info, *obj_struct, VALIDATION_ERROR_2880054a);
2777177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis    }
2778177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis    return skip;
2779177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis}
27805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2781177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlisstatic void PostCallRecordFreeMemory(layer_data *dev_data, VkDeviceMemory mem, DEVICE_MEM_INFO *mem_info, VK_OBJECT obj_struct) {
2782177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis    // Clear mem binding for any bound objects
278347705d01140c9f1492885e6efc5fa262e7e1c6a0Tobin Ehlis    for (auto obj : mem_info->obj_bindings) {
278402a510945ff39f3d9e486e456aca5bfa6ea0c43aMark Lobodzinski        log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, get_debug_report_enum[obj.type], obj.handle, __LINE__,
27857a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski                MEMTRACK_FREED_MEM_REF, "MEM", "VK Object 0x%" PRIxLEAST64 " still has a reference to mem obj 0x%" PRIxLEAST64,
27869b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                obj.handle, HandleToUint64(mem_info->mem));
278747705d01140c9f1492885e6efc5fa262e7e1c6a0Tobin Ehlis        switch (obj.type) {
27887a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski            case kVulkanObjectTypeImage: {
27899a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                auto image_state = GetImageState(dev_data, reinterpret_cast<VkImage &>(obj.handle));
2790cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                assert(image_state);  // Any destroyed images should already be removed from bindings
2791cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                image_state->binding.mem = MEMORY_UNBOUND;
2792cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                break;
2793cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            }
27947a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski            case kVulkanObjectTypeBuffer: {
27959a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                auto buffer_state = GetBufferState(dev_data, reinterpret_cast<VkBuffer &>(obj.handle));
2796cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                assert(buffer_state);  // Any destroyed buffers should already be removed from bindings
2797cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                buffer_state->binding.mem = MEMORY_UNBOUND;
2798cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                break;
2799cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            }
2800cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            default:
2801cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                // Should only have buffer or image objects bound to memory
2802cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                assert(0);
2803177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis        }
2804177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis    }
2805177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis    // Any bound cmd buffers are now invalid
280639c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis    invalidateCommandBuffers(dev_data, mem_info->cb_bindings, obj_struct);
2807177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis    dev_data->memObjMap.erase(mem);
2808177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis}
2809177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis
2810177063aac84fac6f4e650c2629a08b48be643f96Tobin EhlisVKAPI_ATTR void VKAPI_CALL FreeMemory(VkDevice device, VkDeviceMemory mem, const VkAllocationCallbacks *pAllocator) {
281156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
2812177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis    DEVICE_MEM_INFO *mem_info = nullptr;
2813177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis    VK_OBJECT obj_struct;
2814ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
2815177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis    bool skip = PreCallValidateFreeMemory(dev_data, mem, &mem_info, &obj_struct);
2816177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis    if (!skip) {
2817177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis        lock.unlock();
2818177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis        dev_data->dispatch_table.FreeMemory(device, mem, pAllocator);
2819177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis        lock.lock();
2820405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        if (mem != VK_NULL_HANDLE) {
2821405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour            PostCallRecordFreeMemory(dev_data, mem, mem_info, obj_struct);
2822405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        }
282374243a735fe102b370237ddf80d3e6f7ec5246dbMark Mueller    }
28245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
28255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2826f57fc64ac43691ad98e1713886b345465573070aTobin Ehlis// Validate that given Map memory range is valid. This means that the memory should not already be mapped,
2827f57fc64ac43691ad98e1713886b345465573070aTobin Ehlis//  and that the size of the map range should be:
2828f57fc64ac43691ad98e1713886b345465573070aTobin Ehlis//  1. Not zero
2829f57fc64ac43691ad98e1713886b345465573070aTobin Ehlis//  2. Within the size of the memory allocation
283051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool ValidateMapMemRange(layer_data *dev_data, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size) {
28313251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
28325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
28335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (size == 0) {
28343251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
28359b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                       HandleToUint64(mem), __LINE__, MEMTRACK_INVALID_MAP, "MEM",
28363251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                       "VkMapMemory: Attempting to map memory range of size zero");
28375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
28385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
283951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    auto mem_element = dev_data->memObjMap.find(mem);
284051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    if (mem_element != dev_data->memObjMap.end()) {
284157fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis        auto mem_info = mem_element->second.get();
28425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // It is an application error to call VkMapMemory on an object that is already mapped
2843de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis        if (mem_info->mem_range.size != 0) {
28449b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus            skip =
28459b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
28469b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        HandleToUint64(mem), __LINE__, MEMTRACK_INVALID_MAP, "MEM",
28479b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        "VkMapMemory: Attempting to map memory on an already-mapped object 0x%" PRIxLEAST64, HandleToUint64(mem));
28485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
28495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
28505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // Validate that offset + size is within object's allocationSize
28515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (size == VK_WHOLE_SIZE) {
2852de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis            if (offset >= mem_info->alloc_info.allocationSize) {
28533251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
28549b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                               HandleToUint64(mem), __LINE__, MEMTRACK_INVALID_MAP, "MEM",
28553251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                               "Mapping Memory from 0x%" PRIx64 " to 0x%" PRIx64
28563251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                               " with size of VK_WHOLE_SIZE oversteps total array size 0x%" PRIx64,
28573251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                               offset, mem_info->alloc_info.allocationSize, mem_info->alloc_info.allocationSize);
28585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
28595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else {
2860de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis            if ((offset + size) > mem_info->alloc_info.allocationSize) {
28613251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
2862315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                               HandleToUint64(mem), __LINE__, VALIDATION_ERROR_31200552, "MEM",
28633251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                               "Mapping Memory from 0x%" PRIx64 " to 0x%" PRIx64 " oversteps total array size 0x%" PRIx64 ". %s",
28643251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                               offset, size + offset, mem_info->alloc_info.allocationSize,
2865315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                               validation_error_map[VALIDATION_ERROR_31200552]);
28665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
28675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
28685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
28693251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
28705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
28715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
287251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic void storeMemRanges(layer_data *dev_data, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size) {
28739a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto mem_info = GetMemObjInfo(dev_data, mem);
287457fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis    if (mem_info) {
2875de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis        mem_info->mem_range.offset = offset;
2876de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis        mem_info->mem_range.size = size;
28775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
28785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
28795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
288051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool deleteMemRanges(layer_data *dev_data, VkDeviceMemory mem) {
28813251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
28829a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto mem_info = GetMemObjInfo(dev_data, mem);
288357fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis    if (mem_info) {
2884de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis        if (!mem_info->mem_range.size) {
28855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            // Valid Usage: memory must currently be mapped
28863251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
2887315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                           HandleToUint64(mem), __LINE__, VALIDATION_ERROR_33600562, "MEM",
28889b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                           "Unmapping Memory without memory being mapped: mem obj 0x%" PRIxLEAST64 ". %s", HandleToUint64(mem),
2889315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                           validation_error_map[VALIDATION_ERROR_33600562]);
28905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
2891de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis        mem_info->mem_range.size = 0;
28925f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski        if (mem_info->shadow_copy) {
28935f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            free(mem_info->shadow_copy_base);
28945f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            mem_info->shadow_copy_base = 0;
28955f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            mem_info->shadow_copy = 0;
28965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
28975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
28983251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
28995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
29005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
29015f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski// Guard value for pad data
29025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic char NoncoherentMemoryFillValue = 0xb;
29035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
29045f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinskistatic void initializeAndTrackMemory(layer_data *dev_data, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size,
29055f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski                                     void **ppData) {
29069a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto mem_info = GetMemObjInfo(dev_data, mem);
290757fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis    if (mem_info) {
2908de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis        mem_info->p_driver_data = *ppData;
2909de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis        uint32_t index = mem_info->alloc_info.memoryTypeIndex;
2910b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis        if (dev_data->phys_dev_mem_props.memoryTypes[index].propertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) {
29115f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            mem_info->shadow_copy = 0;
29125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else {
29135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (size == VK_WHOLE_SIZE) {
29145f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski                size = mem_info->alloc_info.allocationSize - offset;
29155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
29165f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            mem_info->shadow_pad_size = dev_data->phys_dev_properties.properties.limits.minMemoryMapAlignment;
291716769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton            assert(SafeModulo(mem_info->shadow_pad_size,
29185f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski                                  dev_data->phys_dev_properties.properties.limits.minMemoryMapAlignment) == 0);
29195f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            // Ensure start of mapped region reflects hardware alignment constraints
29205f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            uint64_t map_alignment = dev_data->phys_dev_properties.properties.limits.minMemoryMapAlignment;
29215f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski
29225f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            // From spec: (ppData - offset) must be aligned to at least limits::minMemoryMapAlignment.
29235f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            uint64_t start_offset = offset % map_alignment;
29245f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            // Data passed to driver will be wrapped by a guardband of data to detect over- or under-writes.
2925bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski            mem_info->shadow_copy_base =
2926bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                malloc(static_cast<size_t>(2 * mem_info->shadow_pad_size + size + map_alignment + start_offset));
29275f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski
29285f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            mem_info->shadow_copy =
29295f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski                reinterpret_cast<char *>((reinterpret_cast<uintptr_t>(mem_info->shadow_copy_base) + map_alignment) &
2930bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                         ~(map_alignment - 1)) +
2931bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                start_offset;
293216769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton            assert(SafeModulo(reinterpret_cast<uintptr_t>(mem_info->shadow_copy) + mem_info->shadow_pad_size - start_offset,
29335f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski                                  map_alignment) == 0);
29345f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski
29356e17c244b21ce43ac57404a00a0d844039eed363Mark Lobodzinski            memset(mem_info->shadow_copy, NoncoherentMemoryFillValue, static_cast<size_t>(2 * mem_info->shadow_pad_size + size));
29365f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            *ppData = static_cast<char *>(mem_info->shadow_copy) + mem_info->shadow_pad_size;
29375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
29385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
29395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
29405f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski
2941a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis// Verify that state for fence being waited on is appropriate. That is,
29429867daedbf52debc77d6568162ee21e071699b80Chris Forbes//  a fence being waited on should not already be signaled and
2943a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis//  it should have been submitted on a queue or during acquire next image
294449f6132af865afd5b7f413c91125971ac97c135aChris Forbesstatic inline bool verifyWaitFenceState(layer_data *dev_data, VkFence fence, const char *apiCall) {
29453251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
29469b48b44dd917f95b5f34dd629ec4076fc87eb3a2Chris Forbes
29479a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto pFence = GetFenceNode(dev_data, fence);
29489b48b44dd917f95b5f34dd629ec4076fc87eb3a2Chris Forbes    if (pFence) {
2949cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes        if (pFence->state == FENCE_UNSIGNALED) {
29503251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT,
29519b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(fence), __LINE__, MEMTRACK_INVALID_FENCE_STATE, "MEM",
29523251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "%s called for fence 0x%" PRIxLEAST64
29533251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            " which has not been submitted on a Queue or during "
29543251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "acquire next image.",
29559b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            apiCall, HandleToUint64(fence));
29565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
29575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
29583251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
29595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
2960a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis
2961b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlisstatic void RetireFence(layer_data *dev_data, VkFence fence) {
29629a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto pFence = GetFenceNode(dev_data, fence);
2963b3ecd4c1fb44a2e65dfc13256afa9150aabde1d4Chris Forbes    if (pFence->signaler.first != VK_NULL_HANDLE) {
296425002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski        // Fence signaller is a queue -- use this as proof that prior operations on that queue have completed.
29659a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        RetireWorkOnQueue(dev_data, GetQueueState(dev_data, pFence->signaler.first), pFence->signaler.second);
2966bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski    } else {
296725002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski        // Fence signaller is the WSI. We're not tracking what the WSI op actually /was/ in CV yet, but we need to mark
296825002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski        // the fence as retired.
2969d4513979120463171eb479cdded9336eb9944da1Chris Forbes        pFence->state = FENCE_RETIRED;
2970d4513979120463171eb479cdded9336eb9944da1Chris Forbes    }
2971b3ecd4c1fb44a2e65dfc13256afa9150aabde1d4Chris Forbes}
2972b3ecd4c1fb44a2e65dfc13256afa9150aabde1d4Chris Forbes
2973accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlisstatic bool PreCallValidateWaitForFences(layer_data *dev_data, uint32_t fence_count, const VkFence *fences) {
2974cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.wait_for_fences) return false;
2975accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis    bool skip = false;
2976accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis    for (uint32_t i = 0; i < fence_count; i++) {
2977accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis        skip |= verifyWaitFenceState(dev_data, fences[i], "vkWaitForFences");
2978b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis        skip |= VerifyQueueStateToFence(dev_data, fences[i]);
2979accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis    }
2980accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis    return skip;
2981accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis}
2982accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis
2983b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlisstatic void PostCallRecordWaitForFences(layer_data *dev_data, uint32_t fence_count, const VkFence *fences, VkBool32 wait_all) {
2984b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis    // When we know that all fences are complete we can clean/remove their CBs
2985accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis    if ((VK_TRUE == wait_all) || (1 == fence_count)) {
2986accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis        for (uint32_t i = 0; i < fence_count; i++) {
2987b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis            RetireFence(dev_data, fences[i]);
2988accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis        }
2989accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis    }
2990accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis    // NOTE : Alternate case not handled here is when some fences have completed. In
2991accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis    //  this case for app to guarantee which fences completed it will have to call
2992b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis    //  vkGetFenceStatus() at which point we'll clean/remove their CBs if complete.
2993accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis}
2994accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis
2995bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL WaitForFences(VkDevice device, uint32_t fenceCount, const VkFence *pFences, VkBool32 waitAll,
2996bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                             uint64_t timeout) {
299756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
29985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Verify fence status of submitted fences
2999ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
3000accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis    bool skip = PreCallValidateWaitForFences(dev_data, fenceCount, pFences);
3001b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
3002cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
3003a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis
30044a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.WaitForFences(device, fenceCount, pFences, waitAll, timeout);
3005414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller
30065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (result == VK_SUCCESS) {
3007b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.lock();
3008b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis        PostCallRecordWaitForFences(dev_data, fenceCount, pFences, waitAll);
3009b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.unlock();
30105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
30115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
30125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
30135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
3014f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlisstatic bool PreCallValidateGetFenceStatus(layer_data *dev_data, VkFence fence) {
3015cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.get_fence_state) return false;
3016f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis    return verifyWaitFenceState(dev_data, fence, "vkGetFenceStatus");
3017f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis}
3018f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis
3019b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlisstatic void PostCallRecordGetFenceStatus(layer_data *dev_data, VkFence fence) { RetireFence(dev_data, fence); }
3020f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis
302189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL GetFenceStatus(VkDevice device, VkFence fence) {
302256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
3023ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
3024f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis    bool skip = PreCallValidateGetFenceStatus(dev_data, fence);
3025b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
3026cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
3027a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis
30284a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.GetFenceStatus(device, fence);
30295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (result == VK_SUCCESS) {
3030f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis        lock.lock();
3031b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis        PostCallRecordGetFenceStatus(dev_data, fence);
3032f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis        lock.unlock();
30335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
30345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
30355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
30365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
30373b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlisstatic void PostCallRecordGetDeviceQueue(layer_data *dev_data, uint32_t q_family_index, VkQueue queue) {
30383b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis    // Add queue to tracking set only if it is new
30393b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis    auto result = dev_data->queues.emplace(queue);
30403b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis    if (result.second == true) {
304136c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlis        QUEUE_STATE *queue_state = &dev_data->queueMap[queue];
30423b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis        queue_state->queue = queue;
30433b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis        queue_state->queueFamilyIndex = q_family_index;
30443b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis        queue_state->seq = 0;
30453b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis    }
30463b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis}
30473b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis
3048bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL GetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue *pQueue) {
304956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
30504a0754042cf090e131e9e769d8a3633c228625beChris Forbes    dev_data->dispatch_table.GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);
3051ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    lock_guard_t lock(global_lock);
3052b376edacad6f7ab3fcc0a914e9b1673a9fcd5143Mark Lobodzinski
30533b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis    PostCallRecordGetDeviceQueue(dev_data, queueFamilyIndex, *pQueue);
30545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
30555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
305636c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlisstatic bool PreCallValidateQueueWaitIdle(layer_data *dev_data, VkQueue queue, QUEUE_STATE **queue_state) {
30579a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    *queue_state = GetQueueState(dev_data, queue);
3058cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.queue_wait_idle) return false;
3059e0cec9ec6dd3cfd83345cabba55ec021681801dbTobin Ehlis    return VerifyQueueStateToSeq(dev_data, *queue_state, (*queue_state)->seq + (*queue_state)->submissions.size());
30604273a1c157585a645dca4c960086032793899d05Tobin Ehlis}
30614273a1c157585a645dca4c960086032793899d05Tobin Ehlis
306236c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlisstatic void PostCallRecordQueueWaitIdle(layer_data *dev_data, QUEUE_STATE *queue_state) {
3063e0cec9ec6dd3cfd83345cabba55ec021681801dbTobin Ehlis    RetireWorkOnQueue(dev_data, queue_state, queue_state->seq + queue_state->submissions.size());
30644273a1c157585a645dca4c960086032793899d05Tobin Ehlis}
30654273a1c157585a645dca4c960086032793899d05Tobin Ehlis
306689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL QueueWaitIdle(VkQueue queue) {
306756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map);
306836c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlis    QUEUE_STATE *queue_state = nullptr;
3069ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
30704273a1c157585a645dca4c960086032793899d05Tobin Ehlis    bool skip = PreCallValidateQueueWaitIdle(dev_data, queue, &queue_state);
30719867daedbf52debc77d6568162ee21e071699b80Chris Forbes    lock.unlock();
3072cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
30734a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.QueueWaitIdle(queue);
30744273a1c157585a645dca4c960086032793899d05Tobin Ehlis    if (VK_SUCCESS == result) {
3075e0cec9ec6dd3cfd83345cabba55ec021681801dbTobin Ehlis        lock.lock();
3076e0cec9ec6dd3cfd83345cabba55ec021681801dbTobin Ehlis        PostCallRecordQueueWaitIdle(dev_data, queue_state);
3077e0cec9ec6dd3cfd83345cabba55ec021681801dbTobin Ehlis        lock.unlock();
30784273a1c157585a645dca4c960086032793899d05Tobin Ehlis    }
30795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
30805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
30815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
30828767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlisstatic bool PreCallValidateDeviceWaitIdle(layer_data *dev_data) {
3083cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.device_wait_idle) return false;
30848767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis    bool skip = false;
30858767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis    for (auto &queue : dev_data->queueMap) {
30868767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis        skip |= VerifyQueueStateToSeq(dev_data, &queue.second, queue.second.seq + queue.second.submissions.size());
30878767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis    }
30888767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis    return skip;
30898767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis}
30908767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis
30918767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlisstatic void PostCallRecordDeviceWaitIdle(layer_data *dev_data) {
30928767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis    for (auto &queue : dev_data->queueMap) {
30938767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis        RetireWorkOnQueue(dev_data, &queue.second, queue.second.seq + queue.second.submissions.size());
30948767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis    }
30958767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis}
30968767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis
309789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL DeviceWaitIdle(VkDevice device) {
309856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
3099ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
31008767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis    bool skip = PreCallValidateDeviceWaitIdle(dev_data);
3101b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
3102cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
31034a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.DeviceWaitIdle(device);
31048767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis    if (VK_SUCCESS == result) {
31058767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis        lock.lock();
31068767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis        PostCallRecordDeviceWaitIdle(dev_data);
31078767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis        lock.unlock();
31088767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis    }
31095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
31105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
31115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
31121d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlisstatic bool PreCallValidateDestroyFence(layer_data *dev_data, VkFence fence, FENCE_NODE **fence_node, VK_OBJECT *obj_struct) {
31139a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    *fence_node = GetFenceNode(dev_data, fence);
31149b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus    *obj_struct = {HandleToUint64(fence), kVulkanObjectTypeFence};
3115cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.destroy_fence) return false;
31161d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis    bool skip = false;
31171d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis    if (*fence_node) {
31181d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis        if ((*fence_node)->state == FENCE_INFLIGHT) {
31191d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT,
3120315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(fence), __LINE__, VALIDATION_ERROR_24e008c0, "DS", "Fence 0x%" PRIx64 " is in use. %s",
3121315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(fence), validation_error_map[VALIDATION_ERROR_24e008c0]);
31221d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis        }
31231d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis    }
31241d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis    return skip;
31251d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis}
31261d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis
31271d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlisstatic void PostCallRecordDestroyFence(layer_data *dev_data, VkFence fence) { dev_data->fenceMap.erase(fence); }
31281d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis
312989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL DestroyFence(VkDevice device, VkFence fence, const VkAllocationCallbacks *pAllocator) {
313056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
31311d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis    // Common data objects used pre & post call
31321d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis    FENCE_NODE *fence_node = nullptr;
31331d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis    VK_OBJECT obj_struct;
3134ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
31351d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis    bool skip = PreCallValidateDestroyFence(dev_data, fence, &fence_node, &obj_struct);
31361344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis
31371d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis    if (!skip) {
31381d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis        lock.unlock();
31394a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.DestroyFence(device, fence, pAllocator);
31401d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis        lock.lock();
31411d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis        PostCallRecordDestroyFence(dev_data, fence);
31421d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis    }
31435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
31445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
3145c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlisstatic bool PreCallValidateDestroySemaphore(layer_data *dev_data, VkSemaphore semaphore, SEMAPHORE_NODE **sema_node,
3146c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis                                            VK_OBJECT *obj_struct) {
31479a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    *sema_node = GetSemaphoreNode(dev_data, semaphore);
31489b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus    *obj_struct = {HandleToUint64(semaphore), kVulkanObjectTypeSemaphore};
3149cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.destroy_semaphore) return false;
3150c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis    bool skip = false;
3151c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis    if (*sema_node) {
3152315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= ValidateObjectNotInUse(dev_data, *sema_node, *obj_struct, VALIDATION_ERROR_268008e2);
3153c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis    }
3154c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis    return skip;
3155c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis}
3156c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis
3157c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlisstatic void PostCallRecordDestroySemaphore(layer_data *dev_data, VkSemaphore sema) { dev_data->semaphoreMap.erase(sema); }
3158c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis
3159bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroySemaphore(VkDevice device, VkSemaphore semaphore, const VkAllocationCallbacks *pAllocator) {
316056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
3161c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis    SEMAPHORE_NODE *sema_node;
3162c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis    VK_OBJECT obj_struct;
3163ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
3164c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis    bool skip = PreCallValidateDestroySemaphore(dev_data, semaphore, &sema_node, &obj_struct);
3165eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis    if (!skip) {
3166eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis        lock.unlock();
31674a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.DestroySemaphore(device, semaphore, pAllocator);
3168c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis        lock.lock();
3169c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis        PostCallRecordDestroySemaphore(dev_data, semaphore);
317099d938c90c2f000ee73fb13513dacf84ffa5651fMark Mueller    }
31715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
31725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
31734710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlisstatic bool PreCallValidateDestroyEvent(layer_data *dev_data, VkEvent event, EVENT_STATE **event_state, VK_OBJECT *obj_struct) {
31749a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    *event_state = GetEventNode(dev_data, event);
31759b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus    *obj_struct = {HandleToUint64(event), kVulkanObjectTypeEvent};
3176cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.destroy_event) return false;
3177d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis    bool skip = false;
3178d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis    if (*event_state) {
3179315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= ValidateObjectNotInUse(dev_data, *event_state, *obj_struct, VALIDATION_ERROR_24c008f2);
3180d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis    }
3181d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis    return skip;
3182d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis}
3183d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis
31844710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlisstatic void PostCallRecordDestroyEvent(layer_data *dev_data, VkEvent event, EVENT_STATE *event_state, VK_OBJECT obj_struct) {
318539c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis    invalidateCommandBuffers(dev_data, event_state->cb_bindings, obj_struct);
3186d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis    dev_data->eventMap.erase(event);
3187d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis}
3188d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis
318989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL DestroyEvent(VkDevice device, VkEvent event, const VkAllocationCallbacks *pAllocator) {
319056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
31914710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis    EVENT_STATE *event_state = nullptr;
3192d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis    VK_OBJECT obj_struct;
3193ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
3194d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis    bool skip = PreCallValidateDestroyEvent(dev_data, event, &event_state, &obj_struct);
3195f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis    if (!skip) {
3196f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis        lock.unlock();
31974a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.DestroyEvent(device, event, pAllocator);
3198d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis        lock.lock();
3199405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        if (event != VK_NULL_HANDLE) {
3200405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour            PostCallRecordDestroyEvent(dev_data, event, event_state, obj_struct);
3201405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        }
3202f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis    }
32035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
32045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
320583c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlisstatic bool PreCallValidateDestroyQueryPool(layer_data *dev_data, VkQueryPool query_pool, QUERY_POOL_NODE **qp_state,
320683c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis                                            VK_OBJECT *obj_struct) {
32079a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    *qp_state = GetQueryPoolNode(dev_data, query_pool);
32089b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus    *obj_struct = {HandleToUint64(query_pool), kVulkanObjectTypeQueryPool};
3209cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.destroy_query_pool) return false;
321083c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis    bool skip = false;
321183c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis    if (*qp_state) {
3212315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= ValidateObjectNotInUse(dev_data, *qp_state, *obj_struct, VALIDATION_ERROR_26200632);
321383c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis    }
321483c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis    return skip;
321583c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis}
321683c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis
3217bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic void PostCallRecordDestroyQueryPool(layer_data *dev_data, VkQueryPool query_pool, QUERY_POOL_NODE *qp_state,
3218bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                           VK_OBJECT obj_struct) {
321983c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis    invalidateCommandBuffers(dev_data, qp_state->cb_bindings, obj_struct);
322083c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis    dev_data->queryPoolMap.erase(query_pool);
322183c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis}
322283c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis
3223bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyQueryPool(VkDevice device, VkQueryPool queryPool, const VkAllocationCallbacks *pAllocator) {
322456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
322583c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis    QUERY_POOL_NODE *qp_state = nullptr;
322683c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis    VK_OBJECT obj_struct;
3227ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
322883c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis    bool skip = PreCallValidateDestroyQueryPool(dev_data, queryPool, &qp_state, &obj_struct);
3229f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis    if (!skip) {
3230f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis        lock.unlock();
32314a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.DestroyQueryPool(device, queryPool, pAllocator);
323283c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis        lock.lock();
3233405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        if (queryPool != VK_NULL_HANDLE) {
3234405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour            PostCallRecordDestroyQueryPool(dev_data, queryPool, qp_state, obj_struct);
3235405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        }
3236f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis    }
32375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
32389fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlisstatic bool PreCallValidateGetQueryPoolResults(layer_data *dev_data, VkQueryPool query_pool, uint32_t first_query,
32399fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                                               uint32_t query_count, VkQueryResultFlags flags,
32409fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                                               unordered_map<QueryObject, vector<VkCommandBuffer>> *queries_in_flight) {
3241a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes    // TODO: clean this up, it's insanely wasteful.
3242a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes    for (auto cmd_buffer : dev_data->commandBufferMap) {
3243a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes        if (cmd_buffer.second->in_use.load()) {
3244a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes            for (auto query_state_pair : cmd_buffer.second->queryToStateMap) {
3245a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes                (*queries_in_flight)[query_state_pair.first].push_back(
3246a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes                    cmd_buffer.first);
3247a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes            }
32485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
32495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
3250cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.get_query_pool_results) return false;
32519fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis    bool skip = false;
32529fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis    for (uint32_t i = 0; i < query_count; ++i) {
32539fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis        QueryObject query = {query_pool, first_query + i};
32549fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis        auto qif_pair = queries_in_flight->find(query);
32559fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis        auto query_state_pair = dev_data->queryToStateMap.find(query);
32569fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis        if (query_state_pair != dev_data->queryToStateMap.end()) {
3257ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski            // Available and in flight
32589fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis            if (qif_pair != queries_in_flight->end() && query_state_pair != dev_data->queryToStateMap.end() &&
32599fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                query_state_pair->second) {
32609fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                for (auto cmd_buffer : qif_pair->second) {
32619a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                    auto cb = GetCBNode(dev_data, cmd_buffer);
32629fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                    auto query_event_pair = cb->waitedEventsBeforeQueryReset.find(query);
32639fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                    if (query_event_pair == cb->waitedEventsBeforeQueryReset.end()) {
32649fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
32659fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                                        VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, __LINE__, DRAWSTATE_INVALID_QUERY, "DS",
32669fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                                        "Cannot get query results on queryPool 0x%" PRIx64 " with index %d which is in flight.",
32679b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                        HandleToUint64(query_pool), first_query + i);
3268ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski                    }
3269ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski                }
3270ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski                // Unavailable and in flight
32719fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis            } else if (qif_pair != queries_in_flight->end() && query_state_pair != dev_data->queryToStateMap.end() &&
32729fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                       !query_state_pair->second) {
3273ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski                // TODO : Can there be the same query in use by multiple command buffers in flight?
3274ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski                bool make_available = false;
32759fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                for (auto cmd_buffer : qif_pair->second) {
32769a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                    auto cb = GetCBNode(dev_data, cmd_buffer);
32779fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                    make_available |= cb->queryToStateMap[query];
3278ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski                }
3279ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski                if (!(((flags & VK_QUERY_RESULT_PARTIAL_BIT) || (flags & VK_QUERY_RESULT_WAIT_BIT)) && make_available)) {
32809fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                    skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
32819fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                                    VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, __LINE__, DRAWSTATE_INVALID_QUERY, "DS",
32829fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                                    "Cannot get query results on queryPool 0x%" PRIx64 " with index %d which is unavailable.",
32839b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                    HandleToUint64(query_pool), first_query + i);
32845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
3285ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski                // Unavailable
32869fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis            } else if (query_state_pair != dev_data->queryToStateMap.end() && !query_state_pair->second) {
32879fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0,
32889fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                                __LINE__, DRAWSTATE_INVALID_QUERY, "DS",
32899fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                                "Cannot get query results on queryPool 0x%" PRIx64 " with index %d which is unavailable.",
32909b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                HandleToUint64(query_pool), first_query + i);
32919fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                // Uninitialized
32929fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis            } else if (query_state_pair == dev_data->queryToStateMap.end()) {
32939fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0,
32949fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                                __LINE__, DRAWSTATE_INVALID_QUERY, "DS",
32959fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                                "Cannot get query results on queryPool 0x%" PRIx64
32969fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                                " with index %d as data has not been collected for this index.",
32979b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                HandleToUint64(query_pool), first_query + i);
32985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
32995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
33005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
33019fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis    return skip;
33029fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis}
33039fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis
33049fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlisstatic void PostCallRecordGetQueryPoolResults(layer_data *dev_data, VkQueryPool query_pool, uint32_t first_query,
33059fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                                              uint32_t query_count,
33069fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                                              unordered_map<QueryObject, vector<VkCommandBuffer>> *queries_in_flight) {
33079fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis    for (uint32_t i = 0; i < query_count; ++i) {
33089fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis        QueryObject query = {query_pool, first_query + i};
33099fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis        auto qif_pair = queries_in_flight->find(query);
33109fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis        auto query_state_pair = dev_data->queryToStateMap.find(query);
33119fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis        if (query_state_pair != dev_data->queryToStateMap.end()) {
33129fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis            // Available and in flight
33139fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis            if (qif_pair != queries_in_flight->end() && query_state_pair != dev_data->queryToStateMap.end() &&
33149fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                query_state_pair->second) {
33159fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                for (auto cmd_buffer : qif_pair->second) {
33169a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                    auto cb = GetCBNode(dev_data, cmd_buffer);
33179fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                    auto query_event_pair = cb->waitedEventsBeforeQueryReset.find(query);
33189fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                    if (query_event_pair != cb->waitedEventsBeforeQueryReset.end()) {
33199fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                        for (auto event : query_event_pair->second) {
33209fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                            dev_data->eventMap[event].needsSignaled = true;
33219fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                        }
33229fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                    }
33239fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                }
33249fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis            }
33259fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis        }
33269fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis    }
33279fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis}
33289fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis
33299fdee42cd357379efb9aa27f90beb75d1f824955Tobin EhlisVKAPI_ATTR VkResult VKAPI_CALL GetQueryPoolResults(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount,
33309fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                                                   size_t dataSize, void *pData, VkDeviceSize stride, VkQueryResultFlags flags) {
333156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
33329fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis    unordered_map<QueryObject, vector<VkCommandBuffer>> queries_in_flight;
3333ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
33349fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis    bool skip = PreCallValidateGetQueryPoolResults(dev_data, queryPool, firstQuery, queryCount, flags, &queries_in_flight);
3335b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
3336cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
33379fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis    VkResult result =
33389fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis        dev_data->dispatch_table.GetQueryPoolResults(device, queryPool, firstQuery, queryCount, dataSize, pData, stride, flags);
33399fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis    lock.lock();
33409fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis    PostCallRecordGetQueryPoolResults(dev_data, queryPool, firstQuery, queryCount, &queries_in_flight);
33419fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis    lock.unlock();
33429fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis    return result;
33435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
33445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
3345825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Return true if given ranges intersect, else false
3346825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Prereq : For both ranges, range->end - range->start > 0. This case should have already resulted
3347825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis//  in an error so not checking that here
3348825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// pad_ranges bool indicates a linear and non-linear comparison which requires padding
33493251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski// In the case where padding is required, if an alias is encountered then a validation error is reported and skip
33503251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski//  may be set by the callback function so caller should merge in skip value if padding case is possible.
33512ea938737c34152a86f5e453eaef7f77b45c0ea3Cort Stratton// This check can be skipped by passing skip_checks=true, for call sites outside the validation path.
33523251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinskistatic bool rangesIntersect(layer_data const *dev_data, MEMORY_RANGE const *range1, MEMORY_RANGE const *range2, bool *skip,
33532ea938737c34152a86f5e453eaef7f77b45c0ea3Cort Stratton                            bool skip_checks) {
33543251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    *skip = false;
3355825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    auto r1_start = range1->start;
3356825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    auto r1_end = range1->end;
3357825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    auto r2_start = range2->start;
3358825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    auto r2_end = range2->end;
3359825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    VkDeviceSize pad_align = 1;
3360825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    if (range1->linear != range2->linear) {
3361825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis        pad_align = dev_data->phys_dev_properties.properties.limits.bufferImageGranularity;
3362825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    }
3363cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if ((r1_end & ~(pad_align - 1)) < (r2_start & ~(pad_align - 1))) return false;
3364cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if ((r1_start & ~(pad_align - 1)) > (r2_end & ~(pad_align - 1))) return false;
336547aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski
33662ea938737c34152a86f5e453eaef7f77b45c0ea3Cort Stratton    if (!skip_checks && (range1->linear != range2->linear)) {
336753ecec26e80e4d18b57d24ed6eb91a3c9da4b95cTobin Ehlis        // In linear vs. non-linear case, warn of aliasing
3368825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis        const char *r1_linear_str = range1->linear ? "Linear" : "Non-linear";
3369825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis        const char *r1_type_str = range1->image ? "image" : "buffer";
3370825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis        const char *r2_linear_str = range2->linear ? "linear" : "non-linear";
3371825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis        const char *r2_type_str = range2->image ? "image" : "buffer";
3372825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis        auto obj_type = range1->image ? VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT : VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT;
33733251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        *skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, obj_type, range1->handle, 0,
33743251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                         MEMTRACK_INVALID_ALIASING, "MEM", "%s %s 0x%" PRIx64 " is aliased with %s %s 0x%" PRIx64
33753251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                                           " which may indicate a bug. For further info refer to the "
33763251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                                           "Buffer-Image Granularity section of the Vulkan specification. "
33773251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                                           "(https://www.khronos.org/registry/vulkan/specs/1.0-extensions/"
33783251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                                           "xhtml/vkspec.html#resources-bufferimagegranularity)",
33793251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                         r1_linear_str, r1_type_str, range1->handle, r2_linear_str, r2_type_str, range2->handle);
338047aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski    }
3381825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    // Ranges intersect
3382825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    return true;
338347aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski}
3384623548a271287ae55415e45e3c654ee66d4e79ffTobin Ehlis// Simplified rangesIntersect that calls above function to check range1 for intersection with offset & end addresses
3385c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinskibool rangesIntersect(layer_data const *dev_data, MEMORY_RANGE const *range1, VkDeviceSize offset, VkDeviceSize end) {
3386825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    // Create a local MEMORY_RANGE struct to wrap offset/size
3387825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    MEMORY_RANGE range_wrap;
3388825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    // Synch linear with range1 to avoid padding and potential validation error case
3389825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    range_wrap.linear = range1->linear;
3390825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    range_wrap.start = offset;
3391cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis    range_wrap.end = end;
3392825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    bool tmp_bool;
33932ea938737c34152a86f5e453eaef7f77b45c0ea3Cort Stratton    return rangesIntersect(dev_data, range1, &range_wrap, &tmp_bool, true);
3394825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis}
3395cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis// For given mem_info, set all ranges valid that intersect [offset-end] range
3396cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis// TODO : For ranges where there is no alias, we may want to create new buffer ranges that are valid
3397cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlisstatic void SetMemRangesValid(layer_data const *dev_data, DEVICE_MEM_INFO *mem_info, VkDeviceSize offset, VkDeviceSize end) {
3398cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis    bool tmp_bool = false;
3399f6e16b28b808a342cb92768001afa2cfeee08a11Tobin Ehlis    MEMORY_RANGE map_range = {};
3400cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis    map_range.linear = true;
3401cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis    map_range.start = offset;
3402cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis    map_range.end = end;
3403cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis    for (auto &handle_range_pair : mem_info->bound_ranges) {
34042ea938737c34152a86f5e453eaef7f77b45c0ea3Cort Stratton        if (rangesIntersect(dev_data, &handle_range_pair.second, &map_range, &tmp_bool, false)) {
3405cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis            // TODO : WARN here if tmp_bool true?
3406cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis            handle_range_pair.second.valid = true;
3407cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis        }
3408cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis    }
3409cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis}
34100ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton
34110ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Strattonstatic bool ValidateInsertMemoryRange(layer_data const *dev_data, uint64_t handle, DEVICE_MEM_INFO *mem_info,
34120ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton                                      VkDeviceSize memoryOffset, VkMemoryRequirements memRequirements, bool is_image,
34130ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton                                      bool is_linear, const char *api_name) {
34140ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton    bool skip = false;
34150ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton
34160ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton    MEMORY_RANGE range;
34170ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton    range.image = is_image;
34180ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton    range.handle = handle;
34190ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton    range.linear = is_linear;
34200ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton    range.valid = mem_info->global_valid;
34210ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton    range.memory = mem_info->mem;
34220ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton    range.start = memoryOffset;
34230ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton    range.size = memRequirements.size;
34240ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton    range.end = memoryOffset + memRequirements.size - 1;
34250ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton    range.aliases.clear();
34260ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton
34270ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton    // Check for aliasing problems.
34280ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton    for (auto &obj_range_pair : mem_info->bound_ranges) {
34290ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton        auto check_range = &obj_range_pair.second;
34300ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton        bool intersection_error = false;
34312ea938737c34152a86f5e453eaef7f77b45c0ea3Cort Stratton        if (rangesIntersect(dev_data, &range, check_range, &intersection_error, false)) {
34320ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton            skip |= intersection_error;
34330ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton            range.aliases.insert(check_range);
34340ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton        }
34350ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton    }
34360ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton
34370ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton    if (memoryOffset >= mem_info->alloc_info.allocationSize) {
3438315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        UNIQUE_VALIDATION_ERROR_CODE error_code = is_image ? VALIDATION_ERROR_1740082c : VALIDATION_ERROR_1700080e;
34390ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton        skip = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
34409b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                       HandleToUint64(mem_info->mem), __LINE__, error_code, "MEM",
34410ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton                       "In %s, attempting to bind memory (0x%" PRIxLEAST64 ") to object (0x%" PRIxLEAST64
34420ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton                       "), memoryOffset=0x%" PRIxLEAST64 " must be less than the memory allocation size 0x%" PRIxLEAST64 ". %s",
34439b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                       api_name, HandleToUint64(mem_info->mem), handle, memoryOffset, mem_info->alloc_info.allocationSize,
34449b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                       validation_error_map[error_code]);
34450ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton    }
34460ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton
34470ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton    return skip;
34480ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton}
34490ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton
3450825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Object with given handle is being bound to memory w/ given mem_info struct.
3451825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis//  Track the newly bound memory range with given memoryOffset
3452825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis//  Also scan any previous ranges, track aliased ranges with new range, and flag an error if a linear
3453825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis//  and non-linear range incorrectly overlap.
3454825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Return true if an error is flagged and the user callback returns "true", otherwise false
3455825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// is_image indicates an image object, otherwise handle is for a buffer
3456825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// is_linear indicates a buffer or linear image
34570ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Strattonstatic void InsertMemoryRange(layer_data const *dev_data, uint64_t handle, DEVICE_MEM_INFO *mem_info, VkDeviceSize memoryOffset,
34580ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton                              VkMemoryRequirements memRequirements, bool is_image, bool is_linear) {
34595360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis    MEMORY_RANGE range;
3460825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis
3461825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    range.image = is_image;
346247aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski    range.handle = handle;
3463825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    range.linear = is_linear;
3464f541bf53dee6daf82a4c8304354eac599a884d29Tobin Ehlis    range.valid = mem_info->global_valid;
3465825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    range.memory = mem_info->mem;
346647aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski    range.start = memoryOffset;
3467825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    range.size = memRequirements.size;
346847aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski    range.end = memoryOffset + memRequirements.size - 1;
34695360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis    range.aliases.clear();
34705360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis    // Update Memory aliasing
347175f4c8cec0996021a4258b9bf920a9e0fea4eac1Tobin Ehlis    // Save aliased 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
34725360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis    // inserted into map before loop to get the final ptr, then we may enter loop when not needed & we check range against itself
34735360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis    std::unordered_set<MEMORY_RANGE *> tmp_alias_ranges;
3474825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    for (auto &obj_range_pair : mem_info->bound_ranges) {
3475825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis        auto check_range = &obj_range_pair.second;
34765360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis        bool intersection_error = false;
34772ea938737c34152a86f5e453eaef7f77b45c0ea3Cort Stratton        if (rangesIntersect(dev_data, &range, check_range, &intersection_error, true)) {
3478825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis            range.aliases.insert(check_range);
34795360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis            tmp_alias_ranges.insert(check_range);
3480825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis        }
3481825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    }
34825360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis    mem_info->bound_ranges[handle] = std::move(range);
34835360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis    for (auto tmp_range : tmp_alias_ranges) {
34845360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis        tmp_range->aliases.insert(&mem_info->bound_ranges[handle]);
34855360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis    }
3486825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    if (is_image)
3487825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis        mem_info->bound_images.insert(handle);
3488825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    else
3489825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis        mem_info->bound_buffers.insert(handle);
349047aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski}
349147aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski
34920ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Strattonstatic bool ValidateInsertImageMemoryRange(layer_data const *dev_data, VkImage image, DEVICE_MEM_INFO *mem_info,
34930ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton                                           VkDeviceSize mem_offset, VkMemoryRequirements mem_reqs, bool is_linear,
34940ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton                                           const char *api_name) {
34959b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus    return ValidateInsertMemoryRange(dev_data, HandleToUint64(image), mem_info, mem_offset, mem_reqs, true, is_linear, api_name);
34960ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton}
34970ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Strattonstatic void InsertImageMemoryRange(layer_data const *dev_data, VkImage image, DEVICE_MEM_INFO *mem_info, VkDeviceSize mem_offset,
34980ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton                                   VkMemoryRequirements mem_reqs, bool is_linear) {
34999b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus    InsertMemoryRange(dev_data, HandleToUint64(image), mem_info, mem_offset, mem_reqs, true, is_linear);
3500825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis}
3501825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis
35020ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Strattonstatic bool ValidateInsertBufferMemoryRange(layer_data const *dev_data, VkBuffer buffer, DEVICE_MEM_INFO *mem_info,
35030ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton                                            VkDeviceSize mem_offset, VkMemoryRequirements mem_reqs, const char *api_name) {
35049b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus    return ValidateInsertMemoryRange(dev_data, HandleToUint64(buffer), mem_info, mem_offset, mem_reqs, false, true, api_name);
35050ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton}
35060ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Strattonstatic void InsertBufferMemoryRange(layer_data const *dev_data, VkBuffer buffer, DEVICE_MEM_INFO *mem_info, VkDeviceSize mem_offset,
35070ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton                                    VkMemoryRequirements mem_reqs) {
35089b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus    InsertMemoryRange(dev_data, HandleToUint64(buffer), mem_info, mem_offset, mem_reqs, false, true);
3509825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis}
3510825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis
3511825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Remove MEMORY_RANGE struct for give handle from bound_ranges of mem_info
3512825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis//  is_image indicates if handle is for image or buffer
3513825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis//  This function will also remove the handle-to-index mapping from the appropriate
3514825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis//  map and clean up any aliases for range being removed.
3515825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlisstatic void RemoveMemoryRange(uint64_t handle, DEVICE_MEM_INFO *mem_info, bool is_image) {
3516825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    auto erase_range = &mem_info->bound_ranges[handle];
3517825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    for (auto alias_range : erase_range->aliases) {
3518825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis        alias_range->aliases.erase(erase_range);
351947aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski    }
35205360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis    erase_range->aliases.clear();
3521825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    mem_info->bound_ranges.erase(handle);
35221cba4e1b5940c6818572e05dcad5a3a47fafbc9eTobin Ehlis    if (is_image) {
3523825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis        mem_info->bound_images.erase(handle);
35241cba4e1b5940c6818572e05dcad5a3a47fafbc9eTobin Ehlis    } else {
3525825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis        mem_info->bound_buffers.erase(handle);
35261cba4e1b5940c6818572e05dcad5a3a47fafbc9eTobin Ehlis    }
352747aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski}
352847aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski
3529842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinskivoid RemoveBufferMemoryRange(uint64_t handle, DEVICE_MEM_INFO *mem_info) { RemoveMemoryRange(handle, mem_info, false); }
3530825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis
35318c59133586421be878d393799b30044497f77727Mark Lobodzinskivoid RemoveImageMemoryRange(uint64_t handle, DEVICE_MEM_INFO *mem_info) { RemoveMemoryRange(handle, mem_info, true); }
3532825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis
3533bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyBuffer(VkDevice device, VkBuffer buffer, const VkAllocationCallbacks *pAllocator) {
353456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
3535e1056daefb39e3a3fed0088874725c56a1359e54Tobin Ehlis    BUFFER_STATE *buffer_state = nullptr;
3536e1056daefb39e3a3fed0088874725c56a1359e54Tobin Ehlis    VK_OBJECT obj_struct;
3537ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
3538e1056daefb39e3a3fed0088874725c56a1359e54Tobin Ehlis    bool skip = PreCallValidateDestroyBuffer(dev_data, buffer, &buffer_state, &obj_struct);
3539e1056daefb39e3a3fed0088874725c56a1359e54Tobin Ehlis    if (!skip) {
3540b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.unlock();
35414a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.DestroyBuffer(device, buffer, pAllocator);
3542e1056daefb39e3a3fed0088874725c56a1359e54Tobin Ehlis        lock.lock();
3543405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        if (buffer != VK_NULL_HANDLE) {
3544405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour            PostCallRecordDestroyBuffer(dev_data, buffer, buffer_state, obj_struct);
3545405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        }
354647aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski    }
35475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
35485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
3549bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyBufferView(VkDevice device, VkBufferView bufferView, const VkAllocationCallbacks *pAllocator) {
355056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
3551f61017735c3291a2665487f2bac310578fc60a68Tobin Ehlis    // Common data objects used pre & post call
35528e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis    BUFFER_VIEW_STATE *buffer_view_state = nullptr;
35538e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis    VK_OBJECT obj_struct;
3554ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
35558e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis    // Validate state before calling down chain, update common data if we'll be calling down chain
35568e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis    bool skip = PreCallValidateDestroyBufferView(dev_data, bufferView, &buffer_view_state, &obj_struct);
355738e26abbaa884eb48bfec4ddb4e0ae2c90634e06Tobin Ehlis    if (!skip) {
355838e26abbaa884eb48bfec4ddb4e0ae2c90634e06Tobin Ehlis        lock.unlock();
35594a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.DestroyBufferView(device, bufferView, pAllocator);
35608e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis        lock.lock();
3561405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        if (bufferView != VK_NULL_HANDLE) {
3562405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour            PostCallRecordDestroyBufferView(dev_data, bufferView, buffer_view_state, obj_struct);
3563405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        }
35645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
35655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
35665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
35672a0dd15a44bf665c97a3ff6adcbe7fe5853cdf60Tobin EhlisVKAPI_ATTR void VKAPI_CALL DestroyImage(VkDevice device, VkImage image, const VkAllocationCallbacks *pAllocator) {
356856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
35691facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis    IMAGE_STATE *image_state = nullptr;
35702a0dd15a44bf665c97a3ff6adcbe7fe5853cdf60Tobin Ehlis    VK_OBJECT obj_struct;
3571ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
35722a0dd15a44bf665c97a3ff6adcbe7fe5853cdf60Tobin Ehlis    bool skip = PreCallValidateDestroyImage(dev_data, image, &image_state, &obj_struct);
35732a0dd15a44bf665c97a3ff6adcbe7fe5853cdf60Tobin Ehlis    if (!skip) {
3574f940225c9e5e3e14b3f5a32d3ea360b585614600Tobin Ehlis        lock.unlock();
35754a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.DestroyImage(device, image, pAllocator);
35762a0dd15a44bf665c97a3ff6adcbe7fe5853cdf60Tobin Ehlis        lock.lock();
3577405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        if (image != VK_NULL_HANDLE) {
3578405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour            PostCallRecordDestroyImage(dev_data, image, image_state, obj_struct);
3579405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        }
35805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
35815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
35825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
35834261f1e2c91c90ce040ab36a13c9d92f6e988f10Mark Lobodzinskistatic bool ValidateMemoryTypes(const layer_data *dev_data, const DEVICE_MEM_INFO *mem_info, const uint32_t memory_type_bits,
3584f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen                                const char *funcName, UNIQUE_VALIDATION_ERROR_CODE msgCode) {
35853251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
3586de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis    if (((1 << mem_info->alloc_info.memoryTypeIndex) & memory_type_bits) == 0) {
35873251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
35889b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                       HandleToUint64(mem_info->mem), __LINE__, msgCode, "MT",
35893251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                       "%s(): MemoryRequirements->memoryTypeBits (0x%X) for this object type are not compatible with the memory "
35903251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                       "type (0x%X) of this memory object 0x%" PRIx64 ". %s",
35919b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                       funcName, memory_type_bits, mem_info->alloc_info.memoryTypeIndex, HandleToUint64(mem_info->mem),
35929b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                       validation_error_map[msgCode]);
35934261f1e2c91c90ce040ab36a13c9d92f6e988f10Mark Lobodzinski    }
35943251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
35954261f1e2c91c90ce040ab36a13c9d92f6e988f10Mark Lobodzinski}
35964261f1e2c91c90ce040ab36a13c9d92f6e988f10Mark Lobodzinski
3597160335c453ec51cc48bdef78e8befdb3c86ff292Cort Strattonstatic bool PreCallValidateBindBufferMemory(layer_data *dev_data, VkBuffer buffer, BUFFER_STATE *buffer_state, VkDeviceMemory mem,
3598160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton                                            VkDeviceSize memoryOffset) {
35999207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton    bool skip = false;
36005cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis    if (buffer_state) {
3601ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes        unique_lock_t lock(global_lock);
36029207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton        // Track objects tied to memory
36039b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus        uint64_t buffer_handle = HandleToUint64(buffer);
36047a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski        skip = ValidateSetMemBinding(dev_data, mem, buffer_handle, kVulkanObjectTypeBuffer, "vkBindBufferMemory()");
36052eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis        if (!buffer_state->memory_requirements_checked) {
36062eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis            // There's not an explicit requirement in the spec to call vkGetBufferMemoryRequirements() prior to calling
36079207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton            // BindBufferMemory, but it's implied in that memory being bound must conform with VkMemoryRequirements from
36089207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton            // vkGetBufferMemoryRequirements()
36099207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT,
36109207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton                            buffer_handle, __LINE__, DRAWSTATE_INVALID_BUFFER, "DS",
36119207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton                            "vkBindBufferMemory(): Binding memory to buffer 0x%" PRIxLEAST64
36129207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton                            " but vkGetBufferMemoryRequirements() has not been called on that buffer.",
36139207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton                            buffer_handle);
36142eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis            // Make the call for them so we can verify the state
36152eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis            lock.unlock();
36169207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton            dev_data->dispatch_table.GetBufferMemoryRequirements(dev_data->device, buffer, &buffer_state->requirements);
36172eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis            lock.lock();
36182eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis        }
361947aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski
36200ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton        // Validate bound memory range information
36219a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto mem_info = GetMemObjInfo(dev_data, mem);
362257fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis        if (mem_info) {
36230ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton            skip |= ValidateInsertBufferMemoryRange(dev_data, buffer, mem_info, memoryOffset, buffer_state->requirements,
36240ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton                                                    "vkBindBufferMemory()");
36259207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton            skip |= ValidateMemoryTypes(dev_data, mem_info, buffer_state->requirements.memoryTypeBits, "vkBindBufferMemory()",
3626315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                        VALIDATION_ERROR_17000816);
362747aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski        }
362847aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski
36292c905c8b5aca814df6c680348145ca48885f9f69Dustin Graves        // Validate memory requirements alignment
363016769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton        if (SafeModulo(memoryOffset, buffer_state->requirements.alignment) != 0) {
3631f60e41965223825191505eebc96491bb52e494a2Cort Stratton            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT,
3632315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            buffer_handle, __LINE__, VALIDATION_ERROR_17000818, "DS",
36339207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton                            "vkBindBufferMemory(): memoryOffset is 0x%" PRIxLEAST64
36349207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton                            " but must be an integer multiple of the "
36359207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton                            "VkMemoryRequirements::alignment value 0x%" PRIxLEAST64
36369207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton                            ", returned from a call to vkGetBufferMemoryRequirements with buffer. %s",
3637315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            memoryOffset, buffer_state->requirements.alignment, validation_error_map[VALIDATION_ERROR_17000818]);
36382c905c8b5aca814df6c680348145ca48885f9f69Dustin Graves        }
3639ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller
3640160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton        // Validate memory requirements size
3641160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton        if (buffer_state->requirements.size > (mem_info->alloc_info.allocationSize - memoryOffset)) {
3642160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT,
3643315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            buffer_handle, __LINE__, VALIDATION_ERROR_1700081a, "DS",
3644160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton                            "vkBindBufferMemory(): memory size minus memoryOffset is 0x%" PRIxLEAST64
3645160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton                            " but must be at least as large as "
3646160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton                            "VkMemoryRequirements::size value 0x%" PRIxLEAST64
3647160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton                            ", returned from a call to vkGetBufferMemoryRequirements with buffer. %s",
3648160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton                            mem_info->alloc_info.allocationSize - memoryOffset, buffer_state->requirements.size,
3649315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            validation_error_map[VALIDATION_ERROR_1700081a]);
3650160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton        }
3651160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton
36522c905c8b5aca814df6c680348145ca48885f9f69Dustin Graves        // Validate device limits alignments
3653ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller        static const VkBufferUsageFlagBits usage_list[3] = {
3654ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller            static_cast<VkBufferUsageFlagBits>(VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT),
3655bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski            VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT};
3656bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        static const char *memory_type[3] = {"texel", "uniform", "storage"};
3657bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        static const char *offset_name[3] = {"minTexelBufferOffsetAlignment", "minUniformBufferOffsetAlignment",
3658bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                             "minStorageBufferOffsetAlignment"};
3659cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski
36609207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton        // TODO:  vk_validation_stats.py cannot abide braces immediately preceding or following a validation error enum
3661cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        // clang-format off
3662315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        static const UNIQUE_VALIDATION_ERROR_CODE msgCode[3] = { VALIDATION_ERROR_17000810, VALIDATION_ERROR_17000812,
3663315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis            VALIDATION_ERROR_17000814 };
3664cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        // clang-format on
3665ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller
3666ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller        // Keep this one fresh!
3667ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller        const VkDeviceSize offset_requirement[3] = {
3668ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller            dev_data->phys_dev_properties.properties.limits.minTexelBufferOffsetAlignment,
3669ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller            dev_data->phys_dev_properties.properties.limits.minUniformBufferOffsetAlignment,
3670bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski            dev_data->phys_dev_properties.properties.limits.minStorageBufferOffsetAlignment};
36718718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis        VkBufferUsageFlags usage = dev_data->bufferMap[buffer].get()->createInfo.usage;
3672ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller
3673ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller        for (int i = 0; i < 3; i++) {
3674ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller            if (usage & usage_list[i]) {
367516769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton                if (SafeModulo(memoryOffset, offset_requirement[i]) != 0) {
36769207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton                    skip |= log_msg(
3677f60e41965223825191505eebc96491bb52e494a2Cort Stratton                        dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, buffer_handle,
3678cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                        __LINE__, msgCode[i], "DS", "vkBindBufferMemory(): %s memoryOffset is 0x%" PRIxLEAST64
3679cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                                                    " but must be a multiple of "
3680cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                                                    "device limit %s 0x%" PRIxLEAST64 ". %s",
3681cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                        memory_type[i], memoryOffset, offset_name[i], offset_requirement[i], validation_error_map[msgCode[i]]);
3682ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller                }
36832c905c8b5aca814df6c680348145ca48885f9f69Dustin Graves            }
36842c905c8b5aca814df6c680348145ca48885f9f69Dustin Graves        }
36855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
36869207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton    return skip;
36879207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton}
36889207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton
3689160335c453ec51cc48bdef78e8befdb3c86ff292Cort Strattonstatic void PostCallRecordBindBufferMemory(layer_data *dev_data, VkBuffer buffer, BUFFER_STATE *buffer_state, VkDeviceMemory mem,
3690160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton                                           VkDeviceSize memoryOffset) {
36919207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton    if (buffer_state) {
3692ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes        unique_lock_t lock(global_lock);
36930ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton        // Track bound memory range information
36940ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton        auto mem_info = GetMemObjInfo(dev_data, mem);
36950ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton        if (mem_info) {
36960ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton            InsertBufferMemoryRange(dev_data, buffer, mem_info, memoryOffset, buffer_state->requirements);
36970ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton        }
36980ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton
3699c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton        // Track objects tied to memory
37009b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus        uint64_t buffer_handle = HandleToUint64(buffer);
37017a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski        SetMemBinding(dev_data, mem, buffer_handle, kVulkanObjectTypeBuffer, "vkBindBufferMemory()");
3702c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton
37039207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton        buffer_state->binding.mem = mem;
37049207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton        buffer_state->binding.offset = memoryOffset;
37059207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton        buffer_state->binding.size = buffer_state->requirements.size;
37069207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton    }
37079207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton}
37089207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton
37099207132ef623d47fcbdfeb9ebc796eade35a2f4cCort StrattonVKAPI_ATTR VkResult VKAPI_CALL BindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory mem, VkDeviceSize memoryOffset) {
37109207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
37119207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
3712160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton    auto buffer_state = GetBufferState(dev_data, buffer);
3713160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton    bool skip = PreCallValidateBindBufferMemory(dev_data, buffer, buffer_state, mem, memoryOffset);
37149207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton    if (!skip) {
37154a0754042cf090e131e9e769d8a3633c228625beChris Forbes        result = dev_data->dispatch_table.BindBufferMemory(device, buffer, mem, memoryOffset);
37169207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton        if (result == VK_SUCCESS) {
3717160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton            PostCallRecordBindBufferMemory(dev_data, buffer, buffer_state, mem, memoryOffset);
37189207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton        }
37195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
37205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
37215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
37225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
3723bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL GetBufferMemoryRequirements(VkDevice device, VkBuffer buffer,
3724bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                       VkMemoryRequirements *pMemoryRequirements) {
372556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
372615caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis    dev_data->dispatch_table.GetBufferMemoryRequirements(device, buffer, pMemoryRequirements);
37279a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto buffer_state = GetBufferState(dev_data, buffer);
372815caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis    if (buffer_state) {
372915caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis        buffer_state->requirements = *pMemoryRequirements;
37302eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis        buffer_state->memory_requirements_checked = true;
373115caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis    }
37325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
37335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
3734bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL GetImageMemoryRequirements(VkDevice device, VkImage image, VkMemoryRequirements *pMemoryRequirements) {
373556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
373615caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis    dev_data->dispatch_table.GetImageMemoryRequirements(device, image, pMemoryRequirements);
37379a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto image_state = GetImageState(dev_data, image);
373815caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis    if (image_state) {
373915caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis        image_state->requirements = *pMemoryRequirements;
37402eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis        image_state->memory_requirements_checked = true;
374115caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis    }
37425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
3743593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis
3744bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyImageView(VkDevice device, VkImageView imageView, const VkAllocationCallbacks *pAllocator) {
374556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
3746f61017735c3291a2665487f2bac310578fc60a68Tobin Ehlis    // Common data objects used pre & post call
3747f61017735c3291a2665487f2bac310578fc60a68Tobin Ehlis    IMAGE_VIEW_STATE *image_view_state = nullptr;
3748f61017735c3291a2665487f2bac310578fc60a68Tobin Ehlis    VK_OBJECT obj_struct;
3749ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
3750f61017735c3291a2665487f2bac310578fc60a68Tobin Ehlis    bool skip = PreCallValidateDestroyImageView(dev_data, imageView, &image_view_state, &obj_struct);
3751d85c42a6c1d6ad7a6f684c5bd793aab482b7705cTobin Ehlis    if (!skip) {
3752d85c42a6c1d6ad7a6f684c5bd793aab482b7705cTobin Ehlis        lock.unlock();
37534a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.DestroyImageView(device, imageView, pAllocator);
3754f61017735c3291a2665487f2bac310578fc60a68Tobin Ehlis        lock.lock();
3755405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        if (imageView != VK_NULL_HANDLE) {
3756405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour            PostCallRecordDestroyImageView(dev_data, imageView, image_view_state, obj_struct);
3757405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        }
3758d85c42a6c1d6ad7a6f684c5bd793aab482b7705cTobin Ehlis    }
37595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
37605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
3761bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyShaderModule(VkDevice device, VkShaderModule shaderModule,
3762bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                               const VkAllocationCallbacks *pAllocator) {
376356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
3764918c283ac4f8c604b79abd0c8b5706d2a7352a34Chris Forbes
3765ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
376651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    dev_data->shaderModuleMap.erase(shaderModule);
3767b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
3768918c283ac4f8c604b79abd0c8b5706d2a7352a34Chris Forbes
376951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    dev_data->dispatch_table.DestroyShaderModule(device, shaderModule, pAllocator);
37705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
37715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
37724c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlisstatic bool PreCallValidateDestroyPipeline(layer_data *dev_data, VkPipeline pipeline, PIPELINE_STATE **pipeline_state,
37738bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis                                           VK_OBJECT *obj_struct) {
377494165f5005d1fa37801d49067fe7751789b89d27Tobin Ehlis    *pipeline_state = getPipelineState(dev_data, pipeline);
37759b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus    *obj_struct = {HandleToUint64(pipeline), kVulkanObjectTypePipeline};
3776cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.destroy_pipeline) return false;
37778bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis    bool skip = false;
37788bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis    if (*pipeline_state) {
3779315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= ValidateObjectNotInUse(dev_data, *pipeline_state, *obj_struct, VALIDATION_ERROR_25c005fa);
37808bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis    }
37818bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis    return skip;
37828bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis}
37838bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis
37844c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlisstatic void PostCallRecordDestroyPipeline(layer_data *dev_data, VkPipeline pipeline, PIPELINE_STATE *pipeline_state,
37858bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis                                          VK_OBJECT obj_struct) {
37868bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis    // Any bound cmd buffers are now invalid
378739c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis    invalidateCommandBuffers(dev_data, pipeline_state->cb_bindings, obj_struct);
37880a136bc9fe42c042857c90a421d0426bd0c029efGabríel Arthúr Pétursson    delete getPipelineState(dev_data, pipeline);
37898bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis    dev_data->pipelineMap.erase(pipeline);
37908bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis}
37918bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis
3792bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyPipeline(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks *pAllocator) {
379356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
37944c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis    PIPELINE_STATE *pipeline_state = nullptr;
37958bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis    VK_OBJECT obj_struct;
3796ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
37978bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis    bool skip = PreCallValidateDestroyPipeline(dev_data, pipeline, &pipeline_state, &obj_struct);
3798f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis    if (!skip) {
3799f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis        lock.unlock();
38004a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.DestroyPipeline(device, pipeline, pAllocator);
38018bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis        lock.lock();
3802405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        if (pipeline != VK_NULL_HANDLE) {
3803405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour            PostCallRecordDestroyPipeline(dev_data, pipeline, pipeline_state, obj_struct);
3804405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        }
3805f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis    }
38065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
38075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
3808bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyPipelineLayout(VkDevice device, VkPipelineLayout pipelineLayout,
3809bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                 const VkAllocationCallbacks *pAllocator) {
381056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
3811ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
38126792ea7cc0ce5fa64b7bd6c946460608cbda91c7Tobin Ehlis    dev_data->pipelineLayoutMap.erase(pipelineLayout);
3813e28cddb35c63274c13873b9a7060ad43b255c6f1Tobin Ehlis    lock.unlock();
3814e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis
38154a0754042cf090e131e9e769d8a3633c228625beChris Forbes    dev_data->dispatch_table.DestroyPipelineLayout(device, pipelineLayout, pAllocator);
38165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
38175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
3818d31a44af6da568692a73201825459689c9431867Tobin Ehlisstatic bool PreCallValidateDestroySampler(layer_data *dev_data, VkSampler sampler, SAMPLER_STATE **sampler_state,
3819806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis                                          VK_OBJECT *obj_struct) {
38209a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    *sampler_state = GetSamplerState(dev_data, sampler);
38219b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus    *obj_struct = {HandleToUint64(sampler), kVulkanObjectTypeSampler};
3822cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.destroy_sampler) return false;
3823806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis    bool skip = false;
3824806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis    if (*sampler_state) {
3825315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= ValidateObjectNotInUse(dev_data, *sampler_state, *obj_struct, VALIDATION_ERROR_26600874);
3826806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis    }
3827806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis    return skip;
3828806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis}
3829806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis
3830d31a44af6da568692a73201825459689c9431867Tobin Ehlisstatic void PostCallRecordDestroySampler(layer_data *dev_data, VkSampler sampler, SAMPLER_STATE *sampler_state,
3831806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis                                         VK_OBJECT obj_struct) {
3832806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis    // Any bound cmd buffers are now invalid
3833cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (sampler_state) invalidateCommandBuffers(dev_data, sampler_state->cb_bindings, obj_struct);
3834806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis    dev_data->samplerMap.erase(sampler);
3835806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis}
3836806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis
3837bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroySampler(VkDevice device, VkSampler sampler, const VkAllocationCallbacks *pAllocator) {
383856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
3839d31a44af6da568692a73201825459689c9431867Tobin Ehlis    SAMPLER_STATE *sampler_state = nullptr;
3840806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis    VK_OBJECT obj_struct;
3841ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
3842806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis    bool skip = PreCallValidateDestroySampler(dev_data, sampler, &sampler_state, &obj_struct);
3843f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis    if (!skip) {
3844f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis        lock.unlock();
38454a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.DestroySampler(device, sampler, pAllocator);
3846806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis        lock.lock();
3847405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        if (sampler != VK_NULL_HANDLE) {
3848405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour            PostCallRecordDestroySampler(dev_data, sampler, sampler_state, obj_struct);
3849405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        }
3850f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis    }
38515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
38525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
385379c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlisstatic void PostCallRecordDestroyDescriptorSetLayout(layer_data *dev_data, VkDescriptorSetLayout ds_layout) {
385479c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlis    dev_data->descriptorSetLayoutMap.erase(ds_layout);
385579c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlis}
385679c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlis
3857bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyDescriptorSetLayout(VkDevice device, VkDescriptorSetLayout descriptorSetLayout,
3858bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                      const VkAllocationCallbacks *pAllocator) {
385956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
386079c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlis    dev_data->dispatch_table.DestroyDescriptorSetLayout(device, descriptorSetLayout, pAllocator);
3861ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
386279c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlis    PostCallRecordDestroyDescriptorSetLayout(dev_data, descriptorSetLayout);
38635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
38645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
3865c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlisstatic bool PreCallValidateDestroyDescriptorPool(layer_data *dev_data, VkDescriptorPool pool,
3866a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis                                                 DESCRIPTOR_POOL_STATE **desc_pool_state, VK_OBJECT *obj_struct) {
38679a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    *desc_pool_state = GetDescriptorPoolState(dev_data, pool);
38689b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus    *obj_struct = {HandleToUint64(pool), kVulkanObjectTypeDescriptorPool};
3869cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.destroy_descriptor_pool) return false;
3870c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis    bool skip = false;
3871c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis    if (*desc_pool_state) {
3872315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= ValidateObjectNotInUse(dev_data, *desc_pool_state, *obj_struct, VALIDATION_ERROR_2440025e);
3873c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis    }
3874c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis    return skip;
3875c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis}
3876c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis
3877c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlisstatic void PostCallRecordDestroyDescriptorPool(layer_data *dev_data, VkDescriptorPool descriptorPool,
3878a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis                                                DESCRIPTOR_POOL_STATE *desc_pool_state, VK_OBJECT obj_struct) {
3879c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis    // Any bound cmd buffers are now invalid
388039c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis    invalidateCommandBuffers(dev_data, desc_pool_state->cb_bindings, obj_struct);
3881c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis    // Free sets that were in this pool
3882c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis    for (auto ds : desc_pool_state->sets) {
3883c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis        freeDescriptorSet(dev_data, ds);
3884c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis    }
3885c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis    dev_data->descriptorPoolMap.erase(descriptorPool);
3886ee7e96d032744c1db89cab21362ac8ecad6eec5aGabríel Arthúr Pétursson    delete desc_pool_state;
3887c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis}
3888c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis
3889bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool,
3890bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                 const VkAllocationCallbacks *pAllocator) {
389156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
3892a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis    DESCRIPTOR_POOL_STATE *desc_pool_state = nullptr;
3893c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis    VK_OBJECT obj_struct;
3894ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
3895c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis    bool skip = PreCallValidateDestroyDescriptorPool(dev_data, descriptorPool, &desc_pool_state, &obj_struct);
3896c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis    if (!skip) {
3897c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis        lock.unlock();
3898c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis        dev_data->dispatch_table.DestroyDescriptorPool(device, descriptorPool, pAllocator);
3899c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis        lock.lock();
3900405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        if (descriptorPool != VK_NULL_HANDLE) {
3901405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour            PostCallRecordDestroyDescriptorPool(dev_data, descriptorPool, desc_pool_state, obj_struct);
3902405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        }
3903c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis    }
39045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
39053251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski// Verify cmdBuffer in given cb_node is not in global in-flight set, and return skip result
3906bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis//  If this is a secondary command buffer, then make sure its primary is also in-flight
3907bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis//  If primary is not in-flight, then remove secondary from global in-flight set
3908bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis// This function is only valid at a point when cmdBuffer is being reset or freed
3909cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlisstatic bool checkCommandBufferInFlight(layer_data *dev_data, const GLOBAL_CB_NODE *cb_node, const char *action,
3910cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlis                                       UNIQUE_VALIDATION_ERROR_CODE error_code) {
39113251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
3912a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes    if (cb_node->in_use.load()) {
3913a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
3914a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes                        HandleToUint64(cb_node->commandBuffer), __LINE__, error_code, "DS",
3915a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes                        "Attempt to %s command buffer (0x%p) which is in use. %s", action, cb_node->commandBuffer,
3916a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes                        validation_error_map[error_code]);
3917bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis    }
39183251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
3919bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis}
3920a964cad279f9749cd9ebfc7555247ff3bff26d53Chris Forbes
3921bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis// Iterate over all cmdBuffers in given commandPool and verify that each is not in use
3922cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlisstatic bool checkCommandBuffersInFlight(layer_data *dev_data, COMMAND_POOL_NODE *pPool, const char *action,
3923cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlis                                        UNIQUE_VALIDATION_ERROR_CODE error_code) {
39243251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
3925a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes    for (auto cmd_buffer : pPool->commandBuffers) {
3926a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes        skip |= checkCommandBufferInFlight(dev_data, GetCBNode(dev_data, cmd_buffer), action, error_code);
3927bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis    }
39283251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
3929bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis}
39305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
3931bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL FreeCommandBuffers(VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount,
3932bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                              const VkCommandBuffer *pCommandBuffers) {
393356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
39343251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
3935ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
3936c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes
39375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < commandBufferCount; i++) {
39389a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto cb_node = GetCBNode(dev_data, pCommandBuffers[i]);
39395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // Delete CB information structure, and remove from commandBufferMap
39409f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis        if (cb_node) {
3941315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis            skip |= checkCommandBufferInFlight(dev_data, cb_node, "free", VALIDATION_ERROR_2840005e);
3942c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes        }
3943c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes    }
3944c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes
39453251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (skip) return;
3946c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes
39479a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto pPool = GetCommandPoolNode(dev_data, commandPool);
3948c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes    for (uint32_t i = 0; i < commandBufferCount; i++) {
39499a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto cb_node = GetCBNode(dev_data, pCommandBuffers[i]);
3950c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes        // Delete CB information structure, and remove from commandBufferMap
39519f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis        if (cb_node) {
39525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            // reset prior to delete for data clean-up
3953a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes            // TODO: fix this, it's insane.
39549f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis            resetCB(dev_data, cb_node->commandBuffer);
39559f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis            dev_data->commandBufferMap.erase(cb_node->commandBuffer);
39569f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis            delete cb_node;
39575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
39585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
39595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // Remove commandBuffer reference from commandPoolMap
3960c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes        pPool->commandBuffers.remove(pCommandBuffers[i]);
39615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
3962b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
3963e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis
39644a0754042cf090e131e9e769d8a3633c228625beChris Forbes    dev_data->dispatch_table.FreeCommandBuffers(device, commandPool, commandBufferCount, pCommandBuffers);
39655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
39665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
396789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateCommandPool(VkDevice device, const VkCommandPoolCreateInfo *pCreateInfo,
3968bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                 const VkAllocationCallbacks *pAllocator, VkCommandPool *pCommandPool) {
396956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
39705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
39714a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.CreateCommandPool(device, pCreateInfo, pAllocator, pCommandPool);
39725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
39735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
3974ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes        lock_guard_t lock(global_lock);
39755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        dev_data->commandPoolMap[*pCommandPool].createFlags = pCreateInfo->flags;
39765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        dev_data->commandPoolMap[*pCommandPool].queueFamilyIndex = pCreateInfo->queueFamilyIndex;
39775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
39785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
39795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
39805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
398189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateQueryPool(VkDevice device, const VkQueryPoolCreateInfo *pCreateInfo,
398289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                               const VkAllocationCallbacks *pAllocator, VkQueryPool *pQueryPool) {
398356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
39840c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis    bool skip = false;
39850c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis    if (pCreateInfo && pCreateInfo->queryType == VK_QUERY_TYPE_PIPELINE_STATISTICS) {
39860c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis        if (!dev_data->enabled_features.pipelineStatisticsQuery) {
39870c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0,
3988315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            __LINE__, VALIDATION_ERROR_11c0062e, "DS",
39890c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis                            "Query pool with type VK_QUERY_TYPE_PIPELINE_STATISTICS created on a device "
39900c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis                            "with VkDeviceCreateInfo.pEnabledFeatures.pipelineStatisticsQuery == VK_FALSE. %s",
3991315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            validation_error_map[VALIDATION_ERROR_11c0062e]);
39920c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis        }
39930c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis    }
39940c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis
39950c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
39960c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis    if (!skip) {
39970c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis        result = dev_data->dispatch_table.CreateQueryPool(device, pCreateInfo, pAllocator, pQueryPool);
39980c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis    }
39995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (result == VK_SUCCESS) {
4000ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes        lock_guard_t lock(global_lock);
4001eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis        QUERY_POOL_NODE *qp_node = &dev_data->queryPoolMap[*pQueryPool];
4002eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis        qp_node->createInfo = *pCreateInfo;
40035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
40045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
40055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
40065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
40075f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlisstatic bool PreCallValidateDestroyCommandPool(layer_data *dev_data, VkCommandPool pool, COMMAND_POOL_NODE **cp_state) {
40089a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    *cp_state = GetCommandPoolNode(dev_data, pool);
4009cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.destroy_command_pool) return false;
40105f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis    bool skip = false;
40115f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis    if (*cp_state) {
40125f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis        // Verify that command buffers in pool are complete (not in-flight)
4013315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= checkCommandBuffersInFlight(dev_data, *cp_state, "destroy command pool with", VALIDATION_ERROR_24000052);
40145f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis    }
40155f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis    return skip;
40165f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis}
40175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
40185f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlisstatic void PostCallRecordDestroyCommandPool(layer_data *dev_data, VkCommandPool pool, COMMAND_POOL_NODE *cp_state) {
40199f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis    // Must remove cmdpool from cmdpoolmap, after removing all cmdbuffers in its list from the commandBufferMap
40205f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis    for (auto cb : cp_state->commandBuffers) {
40219a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto cb_node = GetCBNode(dev_data, cb);
40227b34d10b918c1f69e7252174965c6a7a7c35ae05Chris Forbes        clear_cmd_buf_and_mem_references(dev_data, cb_node);
4023d61de0e68063faa169a9a632f811c9c9adec9897Tobin Ehlis        // Remove references to this cb_node prior to delete
4024d61de0e68063faa169a9a632f811c9c9adec9897Tobin Ehlis        // TODO : Need better solution here, resetCB?
40257165385f3a39f1f951f3a6a9a06ed2cce4642b6dMark Lobodzinski        for (auto obj : cb_node->object_bindings) {
40267165385f3a39f1f951f3a6a9a06ed2cce4642b6dMark Lobodzinski            removeCommandBufferBinding(dev_data, &obj, cb_node);
40277165385f3a39f1f951f3a6a9a06ed2cce4642b6dMark Lobodzinski        }
4028d61de0e68063faa169a9a632f811c9c9adec9897Tobin Ehlis        for (auto framebuffer : cb_node->framebuffers) {
40299a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            auto fb_state = GetFramebufferState(dev_data, framebuffer);
4030cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            if (fb_state) fb_state->cb_bindings.erase(cb_node);
4031d61de0e68063faa169a9a632f811c9c9adec9897Tobin Ehlis        }
4032cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        dev_data->commandBufferMap.erase(cb);  // Remove this command buffer
4033cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        delete cb_node;                        // delete CB info structure
4034a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes    }
40355f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis    dev_data->commandPoolMap.erase(pool);
40365f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis}
4037e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis
40385f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis// Destroy commandPool along with all of the commandBuffers allocated from that pool
40395f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin EhlisVKAPI_ATTR void VKAPI_CALL DestroyCommandPool(VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks *pAllocator) {
404056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
40415f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis    COMMAND_POOL_NODE *cp_state = nullptr;
4042ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
40435f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis    bool skip = PreCallValidateDestroyCommandPool(dev_data, commandPool, &cp_state);
40445f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis    if (!skip) {
40455f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis        lock.unlock();
40465f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis        dev_data->dispatch_table.DestroyCommandPool(device, commandPool, pAllocator);
40475f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis        lock.lock();
4048405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        if (commandPool != VK_NULL_HANDLE) {
4049405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour            PostCallRecordDestroyCommandPool(dev_data, commandPool, cp_state);
4050405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        }
40515f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis    }
40525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
40535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
4054bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL ResetCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolResetFlags flags) {
405556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
40563251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
4057400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis
4058ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
40599a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto pPool = GetCommandPoolNode(dev_data, commandPool);
4060315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis    skip |= checkCommandBuffersInFlight(dev_data, pPool, "reset command pool with", VALIDATION_ERROR_32800050);
40611ec6311a8537f4467db08eacbd762ebaa87e70b0Chris Forbes    lock.unlock();
4062a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes
40633251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
40645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
40654a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.ResetCommandPool(device, commandPool, flags);
40665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
40675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Reset all of the CBs allocated from this pool
40685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
40691ec6311a8537f4467db08eacbd762ebaa87e70b0Chris Forbes        lock.lock();
4070a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes        for (auto cmdBuffer : pPool->commandBuffers) {
4071a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes            resetCB(dev_data, cmdBuffer);
40725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
40731ec6311a8537f4467db08eacbd762ebaa87e70b0Chris Forbes        lock.unlock();
40745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
40755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
40765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
40775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
407889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL ResetFences(VkDevice device, uint32_t fenceCount, const VkFence *pFences) {
407956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
40803251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
4081ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
40825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < fenceCount; ++i) {
40839a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto pFence = GetFenceNode(dev_data, pFences[i]);
4084090da73358f71ba026e2474a822fecf55267d166Chris Forbes        if (pFence && pFence->state == FENCE_INFLIGHT) {
4085315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis            skip |=
4086315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT,
4087315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(pFences[i]), __LINE__, VALIDATION_ERROR_32e008c6, "DS", "Fence 0x%" PRIx64 " is in use. %s",
4088315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(pFences[i]), validation_error_map[VALIDATION_ERROR_32e008c6]);
40895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
40905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
4091b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
4092090da73358f71ba026e2474a822fecf55267d166Chris Forbes
40933251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
4094090da73358f71ba026e2474a822fecf55267d166Chris Forbes
40954a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.ResetFences(device, fenceCount, pFences);
4096090da73358f71ba026e2474a822fecf55267d166Chris Forbes
4097090da73358f71ba026e2474a822fecf55267d166Chris Forbes    if (result == VK_SUCCESS) {
4098090da73358f71ba026e2474a822fecf55267d166Chris Forbes        lock.lock();
4099090da73358f71ba026e2474a822fecf55267d166Chris Forbes        for (uint32_t i = 0; i < fenceCount; ++i) {
41009a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            auto pFence = GetFenceNode(dev_data, pFences[i]);
4101090da73358f71ba026e2474a822fecf55267d166Chris Forbes            if (pFence) {
4102090da73358f71ba026e2474a822fecf55267d166Chris Forbes                pFence->state = FENCE_UNSIGNALED;
4103090da73358f71ba026e2474a822fecf55267d166Chris Forbes            }
4104090da73358f71ba026e2474a822fecf55267d166Chris Forbes        }
4105090da73358f71ba026e2474a822fecf55267d166Chris Forbes        lock.unlock();
4106090da73358f71ba026e2474a822fecf55267d166Chris Forbes    }
4107090da73358f71ba026e2474a822fecf55267d166Chris Forbes
41085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
41095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
41105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
4111e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis// For given cb_nodes, invalidate them and track object causing invalidation
41120a4087f99558069e9f6a437ff2dbb5a9c1c22ccaTobin Ehlisvoid invalidateCommandBuffers(const layer_data *dev_data, std::unordered_set<GLOBAL_CB_NODE *> const &cb_nodes, VK_OBJECT obj) {
4113e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis    for (auto cb_node : cb_nodes) {
411439c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis        if (cb_node->state == CB_RECORDING) {
411539c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis            log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
41169b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                    HandleToUint64(cb_node->commandBuffer), __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER, "DS",
4117226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis                    "Invalidating a command buffer that's currently being recorded: 0x%p.", cb_node->commandBuffer);
411846daa701a01b92ae19e3ee9e661d677128fe7e6dChris Forbes            cb_node->state = CB_INVALID_INCOMPLETE;
411946daa701a01b92ae19e3ee9e661d677128fe7e6dChris Forbes        }
412046daa701a01b92ae19e3ee9e661d677128fe7e6dChris Forbes        else {
412146daa701a01b92ae19e3ee9e661d677128fe7e6dChris Forbes            cb_node->state = CB_INVALID_COMPLETE;
412239c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis        }
4123e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis        cb_node->broken_bindings.push_back(obj);
4124db365f522319df6446b50584277a3bbfee1c1052Chris Forbes
4125db365f522319df6446b50584277a3bbfee1c1052Chris Forbes        // if secondary, then propagate the invalidation to the primaries that will call us.
4126db365f522319df6446b50584277a3bbfee1c1052Chris Forbes        if (cb_node->createInfo.level == VK_COMMAND_BUFFER_LEVEL_SECONDARY) {
4127db365f522319df6446b50584277a3bbfee1c1052Chris Forbes            invalidateCommandBuffers(dev_data, cb_node->linkedCommandBuffers, obj);
4128db365f522319df6446b50584277a3bbfee1c1052Chris Forbes        }
4129e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis    }
4130e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis}
4131e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis
4132c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlisstatic bool PreCallValidateDestroyFramebuffer(layer_data *dev_data, VkFramebuffer framebuffer,
4133c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis                                              FRAMEBUFFER_STATE **framebuffer_state, VK_OBJECT *obj_struct) {
41349a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    *framebuffer_state = GetFramebufferState(dev_data, framebuffer);
41359b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus    *obj_struct = {HandleToUint64(framebuffer), kVulkanObjectTypeFramebuffer};
4136cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.destroy_framebuffer) return false;
4137728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis    bool skip = false;
4138728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis    if (*framebuffer_state) {
4139315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= ValidateObjectNotInUse(dev_data, *framebuffer_state, *obj_struct, VALIDATION_ERROR_250006f8);
4140728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis    }
4141728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis    return skip;
4142728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis}
4143728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis
4144c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlisstatic void PostCallRecordDestroyFramebuffer(layer_data *dev_data, VkFramebuffer framebuffer, FRAMEBUFFER_STATE *framebuffer_state,
4145728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis                                             VK_OBJECT obj_struct) {
414639c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis    invalidateCommandBuffers(dev_data, framebuffer_state->cb_bindings, obj_struct);
4147728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis    dev_data->frameBufferMap.erase(framebuffer);
4148728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis}
4149728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis
4150bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyFramebuffer(VkDevice device, VkFramebuffer framebuffer, const VkAllocationCallbacks *pAllocator) {
415156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
4152c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis    FRAMEBUFFER_STATE *framebuffer_state = nullptr;
4153728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis    VK_OBJECT obj_struct;
4154ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
4155728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis    bool skip = PreCallValidateDestroyFramebuffer(dev_data, framebuffer, &framebuffer_state, &obj_struct);
4156728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis    if (!skip) {
4157728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis        lock.unlock();
4158728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis        dev_data->dispatch_table.DestroyFramebuffer(device, framebuffer, pAllocator);
4159728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis        lock.lock();
4160405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        if (framebuffer != VK_NULL_HANDLE) {
4161405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour            PostCallRecordDestroyFramebuffer(dev_data, framebuffer, framebuffer_state, obj_struct);
4162405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        }
41635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
41645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
41655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
41660ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlisstatic bool PreCallValidateDestroyRenderPass(layer_data *dev_data, VkRenderPass render_pass, RENDER_PASS_STATE **rp_state,
41670ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis                                             VK_OBJECT *obj_struct) {
41689a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    *rp_state = GetRenderPassState(dev_data, render_pass);
41699b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus    *obj_struct = {HandleToUint64(render_pass), kVulkanObjectTypeRenderPass};
4170cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.destroy_renderpass) return false;
41710ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis    bool skip = false;
41720ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis    if (*rp_state) {
4173315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= ValidateObjectNotInUse(dev_data, *rp_state, *obj_struct, VALIDATION_ERROR_264006d2);
41740ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis    }
41750ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis    return skip;
41760ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis}
41770ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis
41780ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlisstatic void PostCallRecordDestroyRenderPass(layer_data *dev_data, VkRenderPass render_pass, RENDER_PASS_STATE *rp_state,
41790ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis                                            VK_OBJECT obj_struct) {
418039c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis    invalidateCommandBuffers(dev_data, rp_state->cb_bindings, obj_struct);
41810ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis    dev_data->renderPassMap.erase(render_pass);
41820ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis}
41830ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis
4184bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyRenderPass(VkDevice device, VkRenderPass renderPass, const VkAllocationCallbacks *pAllocator) {
418556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
41860ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis    RENDER_PASS_STATE *rp_state = nullptr;
41870ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis    VK_OBJECT obj_struct;
4188ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
41890ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis    bool skip = PreCallValidateDestroyRenderPass(dev_data, renderPass, &rp_state, &obj_struct);
4190a9fbfe0c622e9fa4b56ddd015ed4c3c409020c2eTobin Ehlis    if (!skip) {
4191a9fbfe0c622e9fa4b56ddd015ed4c3c409020c2eTobin Ehlis        lock.unlock();
41924a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.DestroyRenderPass(device, renderPass, pAllocator);
41930ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis        lock.lock();
4194405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        if (renderPass != VK_NULL_HANDLE) {
4195405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour            PostCallRecordDestroyRenderPass(dev_data, renderPass, rp_state, obj_struct);
4196405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        }
4197a9fbfe0c622e9fa4b56ddd015ed4c3c409020c2eTobin Ehlis    }
41985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
41995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
420089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateBuffer(VkDevice device, const VkBufferCreateInfo *pCreateInfo,
420189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                            const VkAllocationCallbacks *pAllocator, VkBuffer *pBuffer) {
420256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
4203ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
42043683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    bool skip = PreCallValidateCreateBuffer(dev_data, pCreateInfo);
42053683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    lock.unlock();
42063683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski
42073683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
42084a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.CreateBuffer(device, pCreateInfo, pAllocator, pBuffer);
42095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
42105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
42113683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski        lock.lock();
42123683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski        PostCallRecordCreateBuffer(dev_data, pCreateInfo, pBuffer);
42133683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski        lock.unlock();
42145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
42155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
42165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
42175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
421889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateBufferView(VkDevice device, const VkBufferViewCreateInfo *pCreateInfo,
421989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                                const VkAllocationCallbacks *pAllocator, VkBufferView *pView) {
422056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
4221ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
42223251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = PreCallValidateCreateBufferView(dev_data, pCreateInfo);
42238c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young    lock.unlock();
42243251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
42254a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.CreateBufferView(device, pCreateInfo, pAllocator, pView);
42265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
42278c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young        lock.lock();
42283683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski        PostCallRecordCreateBufferView(dev_data, pCreateInfo, pView);
42298c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young        lock.unlock();
42305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
42315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
42325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
42335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
42348dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski// Access helper functions for external modules
4235d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinskiconst VkFormatProperties *GetFormatProperties(core_validation::layer_data *device_data, VkFormat format) {
4236d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski    VkFormatProperties *format_properties = new VkFormatProperties;
4237d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski    instance_layer_data *instance_data =
4238d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski        GetLayerDataPtr(get_dispatch_key(device_data->instance_data->instance), instance_layer_data_map);
4239d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski    instance_data->dispatch_table.GetPhysicalDeviceFormatProperties(device_data->physical_device, format, format_properties);
4240d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski    return format_properties;
42418dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski}
42428dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
4243d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinskiconst VkImageFormatProperties *GetImageFormatProperties(core_validation::layer_data *device_data, VkFormat format,
4244d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski                                                        VkImageType image_type, VkImageTiling tiling, VkImageUsageFlags usage,
4245d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski                                                        VkImageCreateFlags flags) {
4246d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski    VkImageFormatProperties *image_format_properties = new VkImageFormatProperties;
4247d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski    instance_layer_data *instance_data =
4248d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski        GetLayerDataPtr(get_dispatch_key(device_data->instance_data->instance), instance_layer_data_map);
4249d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski    instance_data->dispatch_table.GetPhysicalDeviceImageFormatProperties(device_data->physical_device, format, image_type, tiling,
4250d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski                                                                         usage, flags, image_format_properties);
4251d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski    return image_format_properties;
42528dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski}
42538dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
42547a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlisconst debug_report_data *GetReportData(const core_validation::layer_data *device_data) { return device_data->report_data; }
42558dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
42568dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinskiconst VkPhysicalDeviceProperties *GetPhysicalDeviceProperties(core_validation::layer_data *device_data) {
42578dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    return &device_data->phys_dev_props;
42588dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski}
42598dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
42608c59133586421be878d393799b30044497f77727Mark Lobodzinskiconst CHECK_DISABLED *GetDisables(core_validation::layer_data *device_data) { return &device_data->instance_data->disabled; }
42618c59133586421be878d393799b30044497f77727Mark Lobodzinski
42628c59133586421be878d393799b30044497f77727Mark Lobodzinskistd::unordered_map<VkImage, std::unique_ptr<IMAGE_STATE>> *GetImageMap(core_validation::layer_data *device_data) {
42638c59133586421be878d393799b30044497f77727Mark Lobodzinski    return &device_data->imageMap;
42648c59133586421be878d393799b30044497f77727Mark Lobodzinski}
42658c59133586421be878d393799b30044497f77727Mark Lobodzinski
42668c59133586421be878d393799b30044497f77727Mark Lobodzinskistd::unordered_map<VkImage, std::vector<ImageSubresourcePair>> *GetImageSubresourceMap(core_validation::layer_data *device_data) {
42678c59133586421be878d393799b30044497f77727Mark Lobodzinski    return &device_data->imageSubresourceMap;
42688c59133586421be878d393799b30044497f77727Mark Lobodzinski}
42698c59133586421be878d393799b30044497f77727Mark Lobodzinski
42708c59133586421be878d393799b30044497f77727Mark Lobodzinskistd::unordered_map<ImageSubresourcePair, IMAGE_LAYOUT_NODE> *GetImageLayoutMap(layer_data *device_data) {
42718c59133586421be878d393799b30044497f77727Mark Lobodzinski    return &device_data->imageLayoutMap;
42728c59133586421be878d393799b30044497f77727Mark Lobodzinski}
42738c59133586421be878d393799b30044497f77727Mark Lobodzinski
42740db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlisstd::unordered_map<ImageSubresourcePair, IMAGE_LAYOUT_NODE> const *GetImageLayoutMap(layer_data const *device_data) {
42750db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis    return &device_data->imageLayoutMap;
42760db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis}
42770db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis
42783683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinskistd::unordered_map<VkBuffer, std::unique_ptr<BUFFER_STATE>> *GetBufferMap(layer_data *device_data) {
42793683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    return &device_data->bufferMap;
42803683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski}
42813683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski
42823683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinskistd::unordered_map<VkBufferView, std::unique_ptr<BUFFER_VIEW_STATE>> *GetBufferViewMap(layer_data *device_data) {
42833683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    return &device_data->bufferViewMap;
42843683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski}
42853683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski
42861c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinskistd::unordered_map<VkImageView, std::unique_ptr<IMAGE_VIEW_STATE>> *GetImageViewMap(layer_data *device_data) {
42871c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    return &device_data->imageViewMap;
42881c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski}
42891c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski
4290d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinskiconst PHYS_DEV_PROPERTIES_NODE *GetPhysDevProperties(const layer_data *device_data) {
42916a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    return &device_data->phys_dev_properties;
42926a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski}
42936a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
42945f3e7c34de87353f38bbcd79e12de8af4a9e7695Mark Lobodzinskiconst VkPhysicalDeviceFeatures *GetEnabledFeatures(const layer_data *device_data) {
42955f3e7c34de87353f38bbcd79e12de8af4a9e7695Mark Lobodzinski    return &device_data->enabled_features;
42965f3e7c34de87353f38bbcd79e12de8af4a9e7695Mark Lobodzinski}
42975f3e7c34de87353f38bbcd79e12de8af4a9e7695Mark Lobodzinski
4298a149f1a0cb39b48b19822c8cf9ef2426cd2251dfMark Lobodzinskiconst DeviceExtensions *GetDeviceExtensions(const layer_data *device_data) { return &device_data->extensions; }
42990e2296e24065d02615ee87561bbb80af414a1ddfMike Schuchardt
430089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo,
430189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                           const VkAllocationCallbacks *pAllocator, VkImage *pImage) {
43028dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
430356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
43048dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    bool skip = PreCallValidateCreateImage(dev_data, pCreateInfo, pAllocator, pImage);
43058dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    if (!skip) {
43068dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski        result = dev_data->dispatch_table.CreateImage(device, pCreateInfo, pAllocator, pImage);
43078dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    }
43085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
4309ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes        lock_guard_t lock(global_lock);
4310920311b6aa5614a545cad59521770d0898a75d65Mark Lobodzinski        PostCallRecordCreateImage(dev_data, pCreateInfo, pImage);
43115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
43125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
43135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
43145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
43158c07a094dc9cc4afb6b62181f341c12b9e969041Mark YoungVKAPI_ATTR VkResult VKAPI_CALL CreateImageView(VkDevice device, const VkImageViewCreateInfo *pCreateInfo,
43168c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young                                               const VkAllocationCallbacks *pAllocator, VkImageView *pView) {
431756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
4318ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
4319e3effabf8e97cae8e006477806ceaca62e4f2ce7Tobin Ehlis    bool skip = PreCallValidateCreateImageView(dev_data, pCreateInfo);
43208c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young    lock.unlock();
4321cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
43224a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.CreateImageView(device, pCreateInfo, pAllocator, pView);
43235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
43248c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young        lock.lock();
432579fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis        PostCallRecordCreateImageView(dev_data, pCreateInfo, *pView);
43268c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young        lock.unlock();
43275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
4328bb6624cb996175d8945190886a200e720b3871efChris Forbes
43295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
43305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
43315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
4332bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateFence(VkDevice device, const VkFenceCreateInfo *pCreateInfo,
4333bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                           const VkAllocationCallbacks *pAllocator, VkFence *pFence) {
433456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
43354a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.CreateFence(device, pCreateInfo, pAllocator, pFence);
43365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
4337ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes        lock_guard_t lock(global_lock);
4338a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis        auto &fence_node = dev_data->fenceMap[*pFence];
43398988ad37ea5a054ff2ae3cbe4b767ae6c13cf48bChris Forbes        fence_node.fence = *pFence;
4340a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis        fence_node.createInfo = *pCreateInfo;
4341cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes        fence_node.state = (pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT) ? FENCE_RETIRED : FENCE_UNSIGNALED;
43425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
43435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
43445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
43455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
43465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// TODO handle pipeline caches
434789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreatePipelineCache(VkDevice device, const VkPipelineCacheCreateInfo *pCreateInfo,
434889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                                   const VkAllocationCallbacks *pAllocator, VkPipelineCache *pPipelineCache) {
434956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
43504a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.CreatePipelineCache(device, pCreateInfo, pAllocator, pPipelineCache);
43515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
43525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
43535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
4354bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyPipelineCache(VkDevice device, VkPipelineCache pipelineCache,
4355bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                const VkAllocationCallbacks *pAllocator) {
435656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
43574a0754042cf090e131e9e769d8a3633c228625beChris Forbes    dev_data->dispatch_table.DestroyPipelineCache(device, pipelineCache, pAllocator);
43585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
43595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
4360bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL GetPipelineCacheData(VkDevice device, VkPipelineCache pipelineCache, size_t *pDataSize,
4361bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                    void *pData) {
436256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
43634a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.GetPipelineCacheData(device, pipelineCache, pDataSize, pData);
43645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
43655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
43665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
4367bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL MergePipelineCaches(VkDevice device, VkPipelineCache dstCache, uint32_t srcCacheCount,
4368bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                   const VkPipelineCache *pSrcCaches) {
436956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
43704a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.MergePipelineCaches(device, dstCache, srcCacheCount, pSrcCaches);
43715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
43725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
43735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
43743d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis// utility function to set collective state for pipeline
43754c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlisvoid set_pipeline_state(PIPELINE_STATE *pPipe) {
43763d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis    // If any attachment used by this pipeline has blendEnable, set top-level blendEnable
43773d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis    if (pPipe->graphicsPipelineCI.pColorBlendState) {
43783d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis        for (size_t i = 0; i < pPipe->attachments.size(); ++i) {
43793d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis            if (VK_TRUE == pPipe->attachments[i].blendEnable) {
43803d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis                if (((pPipe->attachments[i].dstAlphaBlendFactor >= VK_BLEND_FACTOR_CONSTANT_COLOR) &&
43813d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis                     (pPipe->attachments[i].dstAlphaBlendFactor <= VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA)) ||
43823d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis                    ((pPipe->attachments[i].dstColorBlendFactor >= VK_BLEND_FACTOR_CONSTANT_COLOR) &&
43833d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis                     (pPipe->attachments[i].dstColorBlendFactor <= VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA)) ||
43843d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis                    ((pPipe->attachments[i].srcAlphaBlendFactor >= VK_BLEND_FACTOR_CONSTANT_COLOR) &&
43853d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis                     (pPipe->attachments[i].srcAlphaBlendFactor <= VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA)) ||
43863d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis                    ((pPipe->attachments[i].srcColorBlendFactor >= VK_BLEND_FACTOR_CONSTANT_COLOR) &&
43873d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis                     (pPipe->attachments[i].srcColorBlendFactor <= VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA))) {
43883d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis                    pPipe->blendConstantsEnabled = true;
43893d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis                }
43903d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis            }
43913d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis        }
43923d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis    }
43933d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis}
43943d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis
4395daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinskibool validate_dual_src_blend_feature(layer_data *device_data, PIPELINE_STATE *pipe_state) {
4396daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski    bool skip = false;
4397daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski    if (pipe_state->graphicsPipelineCI.pColorBlendState) {
4398daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski        for (size_t i = 0; i < pipe_state->attachments.size(); ++i) {
4399daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski            if (!device_data->enabled_features.dualSrcBlend) {
4400daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski                if ((pipe_state->attachments[i].dstAlphaBlendFactor == VK_BLEND_FACTOR_SRC1_COLOR) ||
4401daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski                    (pipe_state->attachments[i].dstAlphaBlendFactor == VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR) ||
4402daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski                    (pipe_state->attachments[i].dstAlphaBlendFactor == VK_BLEND_FACTOR_SRC1_ALPHA) ||
4403daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski                    (pipe_state->attachments[i].dstAlphaBlendFactor == VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA) ||
4404daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski                    (pipe_state->attachments[i].srcAlphaBlendFactor == VK_BLEND_FACTOR_SRC1_COLOR) ||
4405daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski                    (pipe_state->attachments[i].srcAlphaBlendFactor == VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR) ||
4406daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski                    (pipe_state->attachments[i].srcAlphaBlendFactor == VK_BLEND_FACTOR_SRC1_ALPHA) ||
4407daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski                    (pipe_state->attachments[i].srcAlphaBlendFactor == VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA)) {
4408daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski                    skip |=
4409daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski                        log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
44109b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                HandleToUint64(pipe_state->pipeline), __LINE__, DRAWSTATE_INVALID_FEATURE, "DS",
4411daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski                                "CmdBindPipeline: vkPipeline (0x%" PRIxLEAST64 ") attachment[" PRINTF_SIZE_T_SPECIFIER
4412daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski                                "] has a dual-source blend factor but this device feature is not enabled.",
44139b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                HandleToUint64(pipe_state->pipeline), i);
4414daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski                }
4415daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski            }
4416daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski        }
4417daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski    }
4418daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski    return skip;
4419daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski}
4420daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski
4421bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
4422bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                       const VkGraphicsPipelineCreateInfo *pCreateInfos,
4423bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                       const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines) {
44245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // TODO What to do with pipelineCache?
44255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // The order of operations here is a little convoluted but gets the job done
44264c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis    //  1. Pipeline create state is first shadowed into PIPELINE_STATE struct
44275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    //  2. Create state is then validated (which uses flags setup during shadowing)
44285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    //  3. If everything looks good, we'll then create the pipeline and add NODE to pipelineMap
442942486a20f07b16f0c5361cdc00fd789b07b1989aMark Lobodzinski    bool skip = false;
44305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // TODO : Improve this data struct w/ unique_ptrs so cleanup below is automatic
443142486a20f07b16f0c5361cdc00fd789b07b1989aMark Lobodzinski    vector<PIPELINE_STATE *> pipe_state(count);
443256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
44335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
44345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    uint32_t i = 0;
4435ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
44365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
44375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (i = 0; i < count; i++) {
443842486a20f07b16f0c5361cdc00fd789b07b1989aMark Lobodzinski        pipe_state[i] = new PIPELINE_STATE;
443942486a20f07b16f0c5361cdc00fd789b07b1989aMark Lobodzinski        pipe_state[i]->initGraphicsPipeline(&pCreateInfos[i]);
44409a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        pipe_state[i]->render_pass_ci.initialize(GetRenderPassState(dev_data, pCreateInfos[i].renderPass)->createInfo.ptr());
444142486a20f07b16f0c5361cdc00fd789b07b1989aMark Lobodzinski        pipe_state[i]->pipeline_layout = *getPipelineLayout(dev_data, pCreateInfos[i].layout);
44425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
44434260fe87d0d168d6f4e7d65a648be05ebe1dedb3Chris Forbes
44444260fe87d0d168d6f4e7d65a648be05ebe1dedb3Chris Forbes    for (i = 0; i < count; i++) {
44452f521eee4ccb1c84512ea767880df8f38751c0d4Chris Forbes        skip |= ValidatePipelineLocked(dev_data, pipe_state, i);
44464260fe87d0d168d6f4e7d65a648be05ebe1dedb3Chris Forbes    }
44475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
444829243a95b358b0d96ab15064fb3f9b0c0f64b8e9Chris Forbes    lock.unlock();
444929243a95b358b0d96ab15064fb3f9b0c0f64b8e9Chris Forbes
4450c3e70f769bd4aa0988652050444d57cab4925c16Chris Forbes    for (i = 0; i < count; i++) {
4451c3e70f769bd4aa0988652050444d57cab4925c16Chris Forbes        skip |= ValidatePipelineUnlocked(dev_data, pipe_state, i);
4452c3e70f769bd4aa0988652050444d57cab4925c16Chris Forbes    }
4453c3e70f769bd4aa0988652050444d57cab4925c16Chris Forbes
4454c70226063be6148056ceeccf835175a1fd59f24fChris Forbes    if (skip) {
4455c70226063be6148056ceeccf835175a1fd59f24fChris Forbes        for (i = 0; i < count; i++) {
4456c70226063be6148056ceeccf835175a1fd59f24fChris Forbes            delete pipe_state[i];
44571ab616b32d4e5b7d62d4a8c41b0c03ea335ab845Chris Forbes            pPipelines[i] = VK_NULL_HANDLE;
4458c70226063be6148056ceeccf835175a1fd59f24fChris Forbes        }
44597a456d188475c23b566334be45dc0489b2789653Chris Forbes        return VK_ERROR_VALIDATION_FAILED_EXT;
44607a456d188475c23b566334be45dc0489b2789653Chris Forbes    }
44617a456d188475c23b566334be45dc0489b2789653Chris Forbes
4462bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski    auto result =
4463bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        dev_data->dispatch_table.CreateGraphicsPipelines(device, pipelineCache, count, pCreateInfos, pAllocator, pPipelines);
44647a456d188475c23b566334be45dc0489b2789653Chris Forbes    lock.lock();
44657a456d188475c23b566334be45dc0489b2789653Chris Forbes    for (i = 0; i < count; i++) {
446661943a7503bc8594338f3364ef42f1d863486c04Chris Forbes        if (pPipelines[i] == VK_NULL_HANDLE) {
446761943a7503bc8594338f3364ef42f1d863486c04Chris Forbes            delete pipe_state[i];
4468bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        } else {
446961943a7503bc8594338f3364ef42f1d863486c04Chris Forbes            pipe_state[i]->pipeline = pPipelines[i];
447061943a7503bc8594338f3364ef42f1d863486c04Chris Forbes            dev_data->pipelineMap[pipe_state[i]->pipeline] = pipe_state[i];
447161943a7503bc8594338f3364ef42f1d863486c04Chris Forbes        }
44725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
4473c70226063be6148056ceeccf835175a1fd59f24fChris Forbes
44745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
44755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
44765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
4477bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
4478bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                      const VkComputePipelineCreateInfo *pCreateInfos,
4479bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                      const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines) {
44800108a1af0b7c6949846e9d71d00bbfb322b6f7caChris Forbes    bool skip = false;
44815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
44825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // TODO : Improve this data struct w/ unique_ptrs so cleanup below is automatic
44834c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis    vector<PIPELINE_STATE *> pPipeState(count);
448456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
44855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
44865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    uint32_t i = 0;
4487ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
44885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (i = 0; i < count; i++) {
44895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // TODO: Verify compute stage bits
44905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
44915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // Create and initialize internal tracking data structure
44924c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis        pPipeState[i] = new PIPELINE_STATE;
44934c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis        pPipeState[i]->initComputePipeline(&pCreateInfos[i]);
4494c2a5a36d03bbe52f5854a5884346e4a84115e259Tobin Ehlis        pPipeState[i]->pipeline_layout = *getPipelineLayout(dev_data, pCreateInfos[i].layout);
44955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
44965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // TODO: Add Compute Pipeline Verification
4497e446ad08318228362ef35d73e7a0636075cb3636Chris Forbes        skip |= validate_compute_pipeline(dev_data, pPipeState[i]);
44985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
44995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
45007a456d188475c23b566334be45dc0489b2789653Chris Forbes    if (skip) {
45015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (i = 0; i < count; i++) {
45025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            // Clean up any locally allocated data structures
45034c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis            delete pPipeState[i];
4504fcf67c021fdfcbeb12fb04daa9a69ecd7d376c5cChris Forbes            pPipelines[i] = VK_NULL_HANDLE;
45055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
45065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return VK_ERROR_VALIDATION_FAILED_EXT;
45075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
45087a456d188475c23b566334be45dc0489b2789653Chris Forbes
45097a456d188475c23b566334be45dc0489b2789653Chris Forbes    lock.unlock();
4510bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski    auto result =
4511bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        dev_data->dispatch_table.CreateComputePipelines(device, pipelineCache, count, pCreateInfos, pAllocator, pPipelines);
45127a456d188475c23b566334be45dc0489b2789653Chris Forbes    lock.lock();
45137a456d188475c23b566334be45dc0489b2789653Chris Forbes    for (i = 0; i < count; i++) {
4514fcf67c021fdfcbeb12fb04daa9a69ecd7d376c5cChris Forbes        if (pPipelines[i] == VK_NULL_HANDLE) {
4515fcf67c021fdfcbeb12fb04daa9a69ecd7d376c5cChris Forbes            delete pPipeState[i];
4516bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        } else {
4517fcf67c021fdfcbeb12fb04daa9a69ecd7d376c5cChris Forbes            pPipeState[i]->pipeline = pPipelines[i];
4518fcf67c021fdfcbeb12fb04daa9a69ecd7d376c5cChris Forbes            dev_data->pipelineMap[pPipeState[i]->pipeline] = pPipeState[i];
4519fcf67c021fdfcbeb12fb04daa9a69ecd7d376c5cChris Forbes        }
45207a456d188475c23b566334be45dc0489b2789653Chris Forbes    }
45217a456d188475c23b566334be45dc0489b2789653Chris Forbes
45225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
45235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
45245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
452589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateSampler(VkDevice device, const VkSamplerCreateInfo *pCreateInfo,
452689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                             const VkAllocationCallbacks *pAllocator, VkSampler *pSampler) {
452756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
45284a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.CreateSampler(device, pCreateInfo, pAllocator, pSampler);
45295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
4530ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes        lock_guard_t lock(global_lock);
4531d31a44af6da568692a73201825459689c9431867Tobin Ehlis        dev_data->samplerMap[*pSampler] = unique_ptr<SAMPLER_STATE>(new SAMPLER_STATE(pSampler, pCreateInfo));
45325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
45335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
45345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
45355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
45360c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlisstatic bool PreCallValidateCreateDescriptorSetLayout(layer_data *dev_data, const VkDescriptorSetLayoutCreateInfo *create_info) {
4537cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.create_descriptor_set_layout) return false;
45380c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis    return cvdescriptorset::DescriptorSetLayout::ValidateCreateInfo(dev_data->report_data, create_info);
45390c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis}
45400c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis
45410c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlisstatic void PostCallRecordCreateDescriptorSetLayout(layer_data *dev_data, const VkDescriptorSetLayoutCreateInfo *create_info,
45420c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis                                                    VkDescriptorSetLayout set_layout) {
45437e180d382f501c7c04408bda1f5fe79317736a4fTobin Ehlis    dev_data->descriptorSetLayoutMap[set_layout] = std::make_shared<cvdescriptorset::DescriptorSetLayout>(create_info, set_layout);
45440c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis}
45450c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis
4546bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateDescriptorSetLayout(VkDevice device, const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
4547bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                         const VkAllocationCallbacks *pAllocator,
4548bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                         VkDescriptorSetLayout *pSetLayout) {
454956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
45500c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
4551ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
45520c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis    bool skip = PreCallValidateCreateDescriptorSetLayout(dev_data, pCreateInfo);
45530c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis    if (!skip) {
45540c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis        lock.unlock();
45550c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis        result = dev_data->dispatch_table.CreateDescriptorSetLayout(device, pCreateInfo, pAllocator, pSetLayout);
45560c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis        if (VK_SUCCESS == result) {
45570c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis            lock.lock();
45580c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis            PostCallRecordCreateDescriptorSetLayout(dev_data, pCreateInfo, *pSetLayout);
45590c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis        }
45605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
45615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
45625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
45635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
45649e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz// Used by CreatePipelineLayout and CmdPushConstants.
45659e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz// Note that the index argument is optional and only used by CreatePipelineLayout.
45669e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultzstatic bool validatePushConstantRange(const layer_data *dev_data, const uint32_t offset, const uint32_t size,
45679e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz                                      const char *caller_name, uint32_t index = 0) {
4568cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.push_constant_range) return false;
45699e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz    uint32_t const maxPushConstantsSize = dev_data->phys_dev_properties.properties.limits.maxPushConstantsSize;
45703251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
45719e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz    // Check that offset + size don't exceed the max.
45729e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz    // Prevent arithetic overflow here by avoiding addition and testing in this order.
45739e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz    if ((offset >= maxPushConstantsSize) || (size > maxPushConstantsSize - offset)) {
45749e24d8153ab63bc3ac08b5a1517c203930b5de91Karl 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.
45759e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        if (0 == strcmp(caller_name, "vkCreatePipelineLayout()")) {
4576e420dd92dcfc04f279e98796a49ee26b2c3ddafeTobin Ehlis            if (offset >= maxPushConstantsSize) {
45773251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
4578315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                __LINE__, VALIDATION_ERROR_11a0024c, "DS",
45793251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "%s call has push constants index %u with offset %u that "
45803251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "exceeds this device's maxPushConstantSize of %u. %s",
4581315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                caller_name, index, offset, maxPushConstantsSize, validation_error_map[VALIDATION_ERROR_11a0024c]);
4582e420dd92dcfc04f279e98796a49ee26b2c3ddafeTobin Ehlis            }
4583e420dd92dcfc04f279e98796a49ee26b2c3ddafeTobin Ehlis            if (size > maxPushConstantsSize - offset) {
4584315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
4585315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                __LINE__, VALIDATION_ERROR_11a00254, "DS",
4586315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                "%s call has push constants index %u with offset %u and size %u that "
4587315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                "exceeds this device's maxPushConstantSize of %u. %s",
4588315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                caller_name, index, offset, size, maxPushConstantsSize,
4589315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                validation_error_map[VALIDATION_ERROR_11a00254]);
4590e420dd92dcfc04f279e98796a49ee26b2c3ddafeTobin Ehlis            }
45919e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        } else if (0 == strcmp(caller_name, "vkCmdPushConstants()")) {
45924527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton            if (offset >= maxPushConstantsSize) {
45933251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
4594315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                __LINE__, VALIDATION_ERROR_1bc002e4, "DS",
45953251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "%s call has push constants index %u with offset %u that "
45963251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "exceeds this device's maxPushConstantSize of %u. %s",
4597315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                caller_name, index, offset, maxPushConstantsSize, validation_error_map[VALIDATION_ERROR_1bc002e4]);
45984527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton            }
45994527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton            if (size > maxPushConstantsSize - offset) {
4600315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
4601315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                __LINE__, VALIDATION_ERROR_1bc002e6, "DS",
4602315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                "%s call has push constants index %u with offset %u and size %u that "
4603315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                "exceeds this device's maxPushConstantSize of %u. %s",
4604315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                caller_name, index, offset, size, maxPushConstantsSize,
4605315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                validation_error_map[VALIDATION_ERROR_1bc002e6]);
46064527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton            }
46079e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        } else {
46083251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
46093251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            __LINE__, DRAWSTATE_INTERNAL_ERROR, "DS", "%s caller not supported.", caller_name);
46109e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        }
46119e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz    }
46129e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz    // size needs to be non-zero and a multiple of 4.
46139e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz    if ((size == 0) || ((size & 0x3) != 0)) {
46149e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        if (0 == strcmp(caller_name, "vkCreatePipelineLayout()")) {
4615891f13be101e95697e5af9503f06da38b0c48f79Tobin Ehlis            if (size == 0) {
46163251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
4617315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                __LINE__, VALIDATION_ERROR_11a00250, "DS",
46183251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "%s call has push constants index %u with "
46193251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "size %u. Size must be greater than zero. %s",
4620315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                caller_name, index, size, validation_error_map[VALIDATION_ERROR_11a00250]);
4621891f13be101e95697e5af9503f06da38b0c48f79Tobin Ehlis            }
4622891f13be101e95697e5af9503f06da38b0c48f79Tobin Ehlis            if (size & 0x3) {
46233251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
4624315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                __LINE__, VALIDATION_ERROR_11a00252, "DS",
46253251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "%s call has push constants index %u with "
46263251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "size %u. Size must be a multiple of 4. %s",
4627315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                caller_name, index, size, validation_error_map[VALIDATION_ERROR_11a00252]);
4628891f13be101e95697e5af9503f06da38b0c48f79Tobin Ehlis            }
46299e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        } else if (0 == strcmp(caller_name, "vkCmdPushConstants()")) {
46304527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton            if (size == 0) {
46313251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
4632315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                __LINE__, VALIDATION_ERROR_1bc2c21b, "DS",
46333251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "%s call has push constants index %u with "
46343251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "size %u. Size must be greater than zero. %s",
4635315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                caller_name, index, size, validation_error_map[VALIDATION_ERROR_1bc2c21b]);
46364527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton            }
46374527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton            if (size & 0x3) {
46383251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
4639315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                __LINE__, VALIDATION_ERROR_1bc002e2, "DS",
46403251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "%s call has push constants index %u with "
46413251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "size %u. Size must be a multiple of 4. %s",
4642315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                caller_name, index, size, validation_error_map[VALIDATION_ERROR_1bc002e2]);
46434527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton            }
46449e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        } else {
46453251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
46463251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            __LINE__, DRAWSTATE_INTERNAL_ERROR, "DS", "%s caller not supported.", caller_name);
46479e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        }
46489e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz    }
46499e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz    // offset needs to be a multiple of 4.
46509e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz    if ((offset & 0x3) != 0) {
46519e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        if (0 == strcmp(caller_name, "vkCreatePipelineLayout()")) {
46523251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
4653315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            __LINE__, VALIDATION_ERROR_11a0024e, "DS",
46543251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "%s call has push constants index %u with "
46553251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "offset %u. Offset must be a multiple of 4. %s",
4656315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            caller_name, index, offset, validation_error_map[VALIDATION_ERROR_11a0024e]);
46579e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        } else if (0 == strcmp(caller_name, "vkCmdPushConstants()")) {
46583251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
4659315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            __LINE__, VALIDATION_ERROR_1bc002e0, "DS",
46603251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "%s call has push constants with "
46613251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "offset %u. Offset must be a multiple of 4. %s",
4662315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            caller_name, offset, validation_error_map[VALIDATION_ERROR_1bc002e0]);
46639e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        } else {
46643251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
46653251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            __LINE__, DRAWSTATE_INTERNAL_ERROR, "DS", "%s caller not supported.", caller_name);
46669e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        }
46675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
46683251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
46695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
46705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
4671bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo,
467289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                                    const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout) {
46733251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
467456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
4675bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz    // TODO : Add checks for VALIDATION_ERRORS 865-870
46769e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz    // Push Constant Range checks
467707a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz    uint32_t i, j;
46785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (i = 0; i < pCreateInfo->pushConstantRangeCount; ++i) {
46793251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= validatePushConstantRange(dev_data, pCreateInfo->pPushConstantRanges[i].offset,
46803251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                          pCreateInfo->pPushConstantRanges[i].size, "vkCreatePipelineLayout()", i);
46819e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        if (0 == pCreateInfo->pPushConstantRanges[i].stageFlags) {
46823251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
4683315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            __LINE__, VALIDATION_ERROR_11a2dc03, "DS", "vkCreatePipelineLayout() call has no stageFlags set. %s",
4684315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            validation_error_map[VALIDATION_ERROR_11a2dc03]);
46859e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        }
46869e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz    }
46873251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
468807a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz
4689bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz    // As of 1.0.28, there is a VU that states that a stage flag cannot appear more than once in the list of push constant ranges.
469007a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz    for (i = 0; i < pCreateInfo->pushConstantRangeCount; ++i) {
469107a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz        for (j = i + 1; j < pCreateInfo->pushConstantRangeCount; ++j) {
4692bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz            if (0 != (pCreateInfo->pPushConstantRanges[i].stageFlags & pCreateInfo->pPushConstantRanges[j].stageFlags)) {
46933251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
4694315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                __LINE__, VALIDATION_ERROR_0fe00248, "DS",
46953251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "vkCreatePipelineLayout() Duplicate stage flags found in ranges %d and %d. %s", i, j,
4696315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                validation_error_map[VALIDATION_ERROR_0fe00248]);
46979e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz            }
46985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
46995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
4700f73b2046273413ea1338dd714d67c39f8e0fa09eChris Forbes
47014a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.CreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
47025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
4703ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes        lock_guard_t lock(global_lock);
47045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        PIPELINE_LAYOUT_NODE &plNode = dev_data->pipelineLayoutMap[*pPipelineLayout];
470569b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis        plNode.layout = *pPipelineLayout;
4706416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis        plNode.set_layouts.resize(pCreateInfo->setLayoutCount);
47075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (i = 0; i < pCreateInfo->setLayoutCount; ++i) {
47089a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            plNode.set_layouts[i] = GetDescriptorSetLayout(dev_data, pCreateInfo->pSetLayouts[i]);
47095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
4710416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis        plNode.push_constant_ranges.resize(pCreateInfo->pushConstantRangeCount);
47115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (i = 0; i < pCreateInfo->pushConstantRangeCount; ++i) {
4712416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis            plNode.push_constant_ranges[i] = pCreateInfo->pPushConstantRanges[i];
47135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
47145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
47155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
47165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
47175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
4718bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateDescriptorPool(VkDevice device, const VkDescriptorPoolCreateInfo *pCreateInfo,
4719bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                    const VkAllocationCallbacks *pAllocator, VkDescriptorPool *pDescriptorPool) {
472056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
47214a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.CreateDescriptorPool(device, pCreateInfo, pAllocator, pDescriptorPool);
47225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
4723a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis        DESCRIPTOR_POOL_STATE *pNewNode = new DESCRIPTOR_POOL_STATE(*pDescriptorPool, pCreateInfo);
47245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (NULL == pNewNode) {
47255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT,
47269b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        HandleToUint64(*pDescriptorPool), __LINE__, DRAWSTATE_OUT_OF_MEMORY, "DS",
4727a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis                        "Out of memory while attempting to allocate DESCRIPTOR_POOL_STATE in vkCreateDescriptorPool()"))
47285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                return VK_ERROR_VALIDATION_FAILED_EXT;
47295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else {
4730ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes            lock_guard_t lock(global_lock);
47315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            dev_data->descriptorPoolMap[*pDescriptorPool] = pNewNode;
47325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
47335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    } else {
47345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // Need to do anything if pool create fails?
47355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
47365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
47375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
47385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
4739bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL ResetDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool,
4740bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                   VkDescriptorPoolResetFlags flags) {
4741315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis    // TODO : Add checks for VALIDATION_ERROR_32a00272
474256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
47434a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.ResetDescriptorPool(device, descriptorPool, flags);
47445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
4745ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes        lock_guard_t lock(global_lock);
47465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        clearDescriptorPool(dev_data, device, descriptorPool, flags);
47475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
47485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
47495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
47502c4e180a4442f968b44f3d5136f7ffda706f6428Chris Forbes// Ensure the pool contains enough descriptors and descriptor sets to satisfy
4751789832b514862c7a7b5b847eeb8e7cacb733b77bTobin Ehlis// an allocation request. Fills common_data with the total number of descriptors of each type required,
4752789832b514862c7a7b5b847eeb8e7cacb733b77bTobin Ehlis// as well as DescriptorSetLayout ptrs used for later update.
47537f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlisstatic bool PreCallValidateAllocateDescriptorSets(layer_data *dev_data, const VkDescriptorSetAllocateInfo *pAllocateInfo,
47547f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlis                                                  cvdescriptorset::AllocateDescriptorSetsData *common_data) {
47557a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis    // Always update common data
47567a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis    cvdescriptorset::UpdateAllocateDescriptorSetsData(dev_data, pAllocateInfo, common_data);
4757cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.allocate_descriptor_sets) return false;
47587e73e5c6b3020b96a821985f73012f2af0f1b992Tobin Ehlis    // All state checks for AllocateDescriptorSets is done in single function
47597a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis    return cvdescriptorset::ValidateAllocateDescriptorSets(dev_data, pAllocateInfo, common_data);
47607e73e5c6b3020b96a821985f73012f2af0f1b992Tobin Ehlis}
47617e73e5c6b3020b96a821985f73012f2af0f1b992Tobin Ehlis// Allocation state was good and call down chain was made so update state based on allocating descriptor sets
47627e73e5c6b3020b96a821985f73012f2af0f1b992Tobin Ehlisstatic void PostCallRecordAllocateDescriptorSets(layer_data *dev_data, const VkDescriptorSetAllocateInfo *pAllocateInfo,
47637f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlis                                                 VkDescriptorSet *pDescriptorSets,
47647f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlis                                                 const cvdescriptorset::AllocateDescriptorSetsData *common_data) {
47657e73e5c6b3020b96a821985f73012f2af0f1b992Tobin Ehlis    // All the updates are contained in a single cvdescriptorset function
47662c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis    cvdescriptorset::PerformAllocateDescriptorSets(pAllocateInfo, pDescriptorSets, common_data, &dev_data->descriptorPoolMap,
4767b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis                                                   &dev_data->setMap, dev_data);
47682c4e180a4442f968b44f3d5136f7ffda706f6428Chris Forbes}
47692c4e180a4442f968b44f3d5136f7ffda706f6428Chris Forbes
4770827e8708bfc431aa792cba005ebf9f1fe35cc7e3Mark Lobodzinski// TODO: PostCallRecord routine is dependent on data generated in PreCallValidate -- needs to be moved out
4771bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL AllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo *pAllocateInfo,
4772bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                      VkDescriptorSet *pDescriptorSets) {
477356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
4774ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
47757f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlis    cvdescriptorset::AllocateDescriptorSetsData common_data(pAllocateInfo->descriptorSetCount);
47763251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = PreCallValidateAllocateDescriptorSets(dev_data, pAllocateInfo, &common_data);
4777b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
4778d173e0daab123373ce75105f2a908f6ae7cef6abChris Forbes
47793251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
4780d173e0daab123373ce75105f2a908f6ae7cef6abChris Forbes
47814a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.AllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
47826511ce241f7f210211e0c0e882f3c14889071f4dChris Forbes
47835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
4784b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.lock();
47857f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlis        PostCallRecordAllocateDescriptorSets(dev_data, pAllocateInfo, pDescriptorSets, &common_data);
4786b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.unlock();
47875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
47885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
47895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
4790cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis// Verify state before freeing DescriptorSets
4791cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlisstatic bool PreCallValidateFreeDescriptorSets(const layer_data *dev_data, VkDescriptorPool pool, uint32_t count,
4792cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis                                              const VkDescriptorSet *descriptor_sets) {
4793cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.free_descriptor_sets) return false;
47943251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
4795cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis    // First make sure sets being destroyed are not currently in-use
4796405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour    for (uint32_t i = 0; i < count; ++i) {
4797405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        if (descriptor_sets[i] != VK_NULL_HANDLE) {
47983251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= validateIdleDescriptorSet(dev_data, descriptor_sets[i], "vkFreeDescriptorSets");
4799405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        }
4800405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour    }
4801cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis
48029a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    DESCRIPTOR_POOL_STATE *pool_state = GetDescriptorPoolState(dev_data, pool);
4803a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis    if (pool_state && !(VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT & pool_state->createInfo.flags)) {
4804cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis        // Can't Free from a NON_FREE pool
48053251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT,
4806315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(pool), __LINE__, VALIDATION_ERROR_28600270, "DS",
48073251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "It is invalid to call vkFreeDescriptorSets() with a pool created without setting "
48083251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT. %s",
4809315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_28600270]);
4810cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis    }
48113251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
4812cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis}
4813cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis// Sets have been removed from the pool so update underlying state
4814cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlisstatic void PostCallRecordFreeDescriptorSets(layer_data *dev_data, VkDescriptorPool pool, uint32_t count,
4815cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis                                             const VkDescriptorSet *descriptor_sets) {
48169a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    DESCRIPTOR_POOL_STATE *pool_state = GetDescriptorPoolState(dev_data, pool);
4817cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis    // Update available descriptor sets in pool
4818cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis    pool_state->availableSets += count;
4819cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis
4820cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis    // For each freed descriptor add its resources back into the pool as available and remove from pool and setMap
4821cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis    for (uint32_t i = 0; i < count; ++i) {
4822405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        if (descriptor_sets[i] != VK_NULL_HANDLE) {
4823405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour            auto descriptor_set = dev_data->setMap[descriptor_sets[i]];
4824405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour            uint32_t type_index = 0, descriptor_count = 0;
4825405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour            for (uint32_t j = 0; j < descriptor_set->GetBindingCount(); ++j) {
4826405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour                type_index = static_cast<uint32_t>(descriptor_set->GetTypeFromIndex(j));
4827405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour                descriptor_count = descriptor_set->GetDescriptorCountFromIndex(j);
4828405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour                pool_state->availableDescriptorTypeCount[type_index] += descriptor_count;
4829405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour            }
4830405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour            freeDescriptorSet(dev_data, descriptor_set);
4831405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour            pool_state->sets.erase(descriptor_set);
4832405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        }
4833cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis    }
4834cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis}
48355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
4836bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL FreeDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool, uint32_t count,
4837bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                  const VkDescriptorSet *pDescriptorSets) {
483856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
48395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Make sure that no sets being destroyed are in-flight
4840ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
48413251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = PreCallValidateFreeDescriptorSets(dev_data, descriptorPool, count, pDescriptorSets);
4842b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
4843e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis
48443251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
48454a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.FreeDescriptorSets(device, descriptorPool, count, pDescriptorSets);
48465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
4847b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.lock();
4848cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis        PostCallRecordFreeDescriptorSets(dev_data, descriptorPool, count, pDescriptorSets);
4849b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.unlock();
48505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
48515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
48525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
48536b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis// TODO : This is a Proof-of-concept for core validation architecture
48546b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis//  Really we'll want to break out these functions to separate files but
48556b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis//  keeping it all together here to prove out design
48566b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis// PreCallValidate* handles validating all of the state prior to calling down chain to UpdateDescriptorSets()
48576b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlisstatic bool PreCallValidateUpdateDescriptorSets(layer_data *dev_data, uint32_t descriptorWriteCount,
48586b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis                                                const VkWriteDescriptorSet *pDescriptorWrites, uint32_t descriptorCopyCount,
48596b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis                                                const VkCopyDescriptorSet *pDescriptorCopies) {
4860cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.update_descriptor_sets) return false;
48616b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis    // First thing to do is perform map look-ups.
48626b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis    // NOTE : UpdateDescriptorSets is somewhat unique in that it's operating on a number of DescriptorSets
48636b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis    //  so we can't just do a single map look-up up-front, but do them individually in functions below
48646b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis
48656b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis    // Now make call(s) that validate state, but don't perform state updates in this function
48666b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis    // Note, here DescriptorSets is unique in that we don't yet have an instance. Using a helper function in the
48676b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis    //  namespace which will parse params and make calls into specific class instances
4868104ab082916e41467ef60baaab7a5a8b2e02c59cTobin Ehlis    return cvdescriptorset::ValidateUpdateDescriptorSets(dev_data->report_data, dev_data, descriptorWriteCount, pDescriptorWrites,
4869104ab082916e41467ef60baaab7a5a8b2e02c59cTobin Ehlis                                                         descriptorCopyCount, pDescriptorCopies);
48706b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis}
48716b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis// PostCallRecord* handles recording state updates following call down chain to UpdateDescriptorSets()
48720c9526fb9fbc2d95ebda8902e1de9d9007ba4e9eTobin Ehlisstatic void PreCallRecordUpdateDescriptorSets(layer_data *dev_data, uint32_t descriptorWriteCount,
48730c9526fb9fbc2d95ebda8902e1de9d9007ba4e9eTobin Ehlis                                              const VkWriteDescriptorSet *pDescriptorWrites, uint32_t descriptorCopyCount,
48740c9526fb9fbc2d95ebda8902e1de9d9007ba4e9eTobin Ehlis                                              const VkCopyDescriptorSet *pDescriptorCopies) {
4875104ab082916e41467ef60baaab7a5a8b2e02c59cTobin Ehlis    cvdescriptorset::PerformUpdateDescriptorSets(dev_data, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount,
48766b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis                                                 pDescriptorCopies);
48776b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis}
48785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
4879bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL UpdateDescriptorSets(VkDevice device, uint32_t descriptorWriteCount,
4880bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                const VkWriteDescriptorSet *pDescriptorWrites, uint32_t descriptorCopyCount,
4881bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                const VkCopyDescriptorSet *pDescriptorCopies) {
48826b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis    // Only map look-up at top level is for device-level layer_data
488356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
4884ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
48853251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = PreCallValidateUpdateDescriptorSets(dev_data, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount,
48863251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                                    pDescriptorCopies);
48873251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (!skip) {
48880c9526fb9fbc2d95ebda8902e1de9d9007ba4e9eTobin Ehlis        // Since UpdateDescriptorSets() is void, nothing to check prior to updating state & we can update before call down chain
48890c9526fb9fbc2d95ebda8902e1de9d9007ba4e9eTobin Ehlis        PreCallRecordUpdateDescriptorSets(dev_data, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount,
48900c9526fb9fbc2d95ebda8902e1de9d9007ba4e9eTobin Ehlis                                          pDescriptorCopies);
48910c9526fb9fbc2d95ebda8902e1de9d9007ba4e9eTobin Ehlis        lock.unlock();
48924a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.UpdateDescriptorSets(device, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount,
48934a0754042cf090e131e9e769d8a3633c228625beChris Forbes                                                      pDescriptorCopies);
48945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
48955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
48965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
4897bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL AllocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo *pCreateInfo,
4898bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                      VkCommandBuffer *pCommandBuffer) {
489956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
49004a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.AllocateCommandBuffers(device, pCreateInfo, pCommandBuffer);
49015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
4902ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes        unique_lock_t lock(global_lock);
49039a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto pPool = GetCommandPoolNode(dev_data, pCreateInfo->commandPool);
4904cd9a648074f67a1d44c15a056b90fc66da8ead17Chris Forbes
4905cd9a648074f67a1d44c15a056b90fc66da8ead17Chris Forbes        if (pPool) {
490672d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis            for (uint32_t i = 0; i < pCreateInfo->commandBufferCount; i++) {
49075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                // Add command buffer to its commandPool map
4908cd9a648074f67a1d44c15a056b90fc66da8ead17Chris Forbes                pPool->commandBuffers.push_back(pCommandBuffer[i]);
49095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                GLOBAL_CB_NODE *pCB = new GLOBAL_CB_NODE;
49105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                // Add command buffer to map
49115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                dev_data->commandBufferMap[pCommandBuffer[i]] = pCB;
49125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                resetCB(dev_data, pCommandBuffer[i]);
49135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                pCB->createInfo = *pCreateInfo;
49145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                pCB->device = device;
49155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
49165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
4917b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.unlock();
49185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
49195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
49205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
49215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
4922883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis// Add bindings between the given cmd buffer & framebuffer and the framebuffer's children
4923c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlisstatic void AddFramebufferBinding(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, FRAMEBUFFER_STATE *fb_state) {
49249b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus    addCommandBufferBinding(&fb_state->cb_bindings, {HandleToUint64(fb_state->framebuffer), kVulkanObjectTypeFramebuffer},
49250245b74a083d2cb3b083571deb0fe13b4ab428a4Tobin Ehlis                            cb_state);
4926883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis    for (auto attachment : fb_state->attachments) {
4927883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis        auto view_state = attachment.view_state;
4928883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis        if (view_state) {
492903ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis            AddCommandBufferBindingImageView(dev_data, cb_state, view_state);
4930883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis        }
49319a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto rp_state = GetRenderPassState(dev_data, fb_state->createInfo.renderPass);
4932883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis        if (rp_state) {
49339b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus            addCommandBufferBinding(&rp_state->cb_bindings, {HandleToUint64(rp_state->renderPass), kVulkanObjectTypeRenderPass},
49349b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                    cb_state);
4935883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis        }
4936883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis    }
4937883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis}
4938883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis
4939bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL BeginCommandBuffer(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo *pBeginInfo) {
49403251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
494156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
4942ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
49435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Validate command buffer level
49449a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *cb_node = GetCBNode(dev_data, commandBuffer);
4945f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis    if (cb_node) {
49465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // This implicitly resets the Cmd Buffer so make sure any fence is done and then clear memory references
4947a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes        if (cb_node->in_use.load()) {
49483251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
4949315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_16e00062, "MEM",
495059ae0ccadec962d9ca2cce7584fad6c57c1a4458Tobin Ehlis                            "Calling vkBeginCommandBuffer() on active command buffer %p before it has completed. "
49513251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "You must check command buffer fence before this call. %s",
4952315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            commandBuffer, validation_error_map[VALIDATION_ERROR_16e00062]);
49535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
4954f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis        clear_cmd_buf_and_mem_references(dev_data, cb_node);
4955f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis        if (cb_node->createInfo.level != VK_COMMAND_BUFFER_LEVEL_PRIMARY) {
49565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            // Secondary Command Buffer
49575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            const VkCommandBufferInheritanceInfo *pInfo = pBeginInfo->pInheritanceInfo;
49585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (!pInfo) {
49593251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |=
49605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
4961315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_16e00066, "DS",
4962bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                            "vkBeginCommandBuffer(): Secondary Command Buffer (0x%p) must have inheritance info. %s", commandBuffer,
4963315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            validation_error_map[VALIDATION_ERROR_16e00066]);
49645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            } else {
49655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                if (pBeginInfo->flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT) {
49662c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis                    assert(pInfo->renderPass);
49672c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis                    string errorString = "";
49689a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                    auto framebuffer = GetFramebufferState(dev_data, pInfo->framebuffer);
49692c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis                    if (framebuffer) {
49702c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis                        if ((framebuffer->createInfo.renderPass != pInfo->renderPass) &&
49712c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis                            !verify_renderpass_compatibility(dev_data, framebuffer->renderPassCreateInfo.ptr(),
49729a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                                                             GetRenderPassState(dev_data, pInfo->renderPass)->createInfo.ptr(),
49732c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis                                                             errorString)) {
49742c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis                            // renderPass that framebuffer was created with must be compatible with local renderPass
49753251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
49769b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                            VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, HandleToUint64(commandBuffer), __LINE__,
4977315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                            VALIDATION_ERROR_0280006e, "DS",
49783251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                            "vkBeginCommandBuffer(): Secondary Command "
49793251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                            "Buffer (0x%p) renderPass (0x%" PRIxLEAST64
49803251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                            ") is incompatible w/ framebuffer "
49813251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                            "(0x%" PRIxLEAST64 ") w/ render pass (0x%" PRIxLEAST64 ") due to: %s. %s",
49829b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                            commandBuffer, HandleToUint64(pInfo->renderPass), HandleToUint64(pInfo->framebuffer),
49839b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                            HandleToUint64(framebuffer->createInfo.renderPass), errorString.c_str(),
4984315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                            validation_error_map[VALIDATION_ERROR_0280006e]);
49855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        }
49862c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis                        // Connect this framebuffer and its children to this cmdBuffer
49872c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis                        AddFramebufferBinding(dev_data, cb_node, framebuffer);
49885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    }
49895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
49904527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton                if ((pInfo->occlusionQueryEnable == VK_FALSE || dev_data->enabled_features.occlusionQueryPrecise == VK_FALSE) &&
49915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    (pInfo->queryFlags & VK_QUERY_CONTROL_PRECISE_BIT)) {
49923251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
49939b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                    VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, HandleToUint64(commandBuffer), __LINE__,
4994315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    VALIDATION_ERROR_16e00068, "DS",
49953251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    "vkBeginCommandBuffer(): Secondary Command Buffer (0x%p) must not have "
49963251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    "VK_QUERY_CONTROL_PRECISE_BIT if occulusionQuery is disabled or the device does not "
49973251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    "support precise occlusion queries. %s",
4998315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    commandBuffer, validation_error_map[VALIDATION_ERROR_16e00068]);
49995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
50005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
50015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (pInfo && pInfo->renderPass != VK_NULL_HANDLE) {
50029a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                auto renderPass = GetRenderPassState(dev_data, pInfo->renderPass);
500316387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes                if (renderPass) {
5004fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes                    if (pInfo->subpass >= renderPass->createInfo.subpassCount) {
50053251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
50069b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                        VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, HandleToUint64(commandBuffer), __LINE__,
5007315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                        VALIDATION_ERROR_0280006c, "DS",
50083251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                        "vkBeginCommandBuffer(): Secondary Command Buffers (0x%p) must have a subpass index (%d) "
50093251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                        "that is less than the number of subpasses (%d). %s",
50103251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                        commandBuffer, pInfo->subpass, renderPass->createInfo.subpassCount,
5011315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                        validation_error_map[VALIDATION_ERROR_0280006c]);
50125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    }
50135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
50145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
50155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
5016f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis        if (CB_RECORDING == cb_node->state) {
50173251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
5018315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_16e00062, "DS",
50193251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "vkBeginCommandBuffer(): Cannot call Begin on command buffer (0x%p"
50203251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            ") in the RECORDING state. Must first call vkEndCommandBuffer(). %s",
5021315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            commandBuffer, validation_error_map[VALIDATION_ERROR_16e00062]);
502246daa701a01b92ae19e3ee9e661d677128fe7e6dChris Forbes        } else if (CB_RECORDED == cb_node->state || CB_INVALID_COMPLETE == cb_node->state) {
5023f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis            VkCommandPool cmdPool = cb_node->createInfo.commandPool;
50249a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            auto pPool = GetCommandPoolNode(dev_data, cmdPool);
5025cd9a648074f67a1d44c15a056b90fc66da8ead17Chris Forbes            if (!(VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT & pPool->createFlags)) {
50263251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |=
50275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
5028315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_16e00064, "DS",
5029226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis                            "Call to vkBeginCommandBuffer() on command buffer (0x%p"
5030414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                            ") attempts to implicitly reset cmdBuffer created from command pool (0x%" PRIxLEAST64
50314527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton                            ") that does NOT have the VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT bit set. %s",
5032315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            commandBuffer, HandleToUint64(cmdPool), validation_error_map[VALIDATION_ERROR_16e00064]);
50335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
50345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            resetCB(dev_data, commandBuffer);
50355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
50365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // Set updated state here in case implicit reset occurs above
5037f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis        cb_node->state = CB_RECORDING;
5038f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis        cb_node->beginInfo = *pBeginInfo;
5039f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis        if (cb_node->beginInfo.pInheritanceInfo) {
5040f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis            cb_node->inheritanceInfo = *(cb_node->beginInfo.pInheritanceInfo);
5041f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis            cb_node->beginInfo.pInheritanceInfo = &cb_node->inheritanceInfo;
5042888e1d268098177fde4a2263e3d7b7cc415f1debMark Young            // If we are a secondary command-buffer and inheriting.  Update the items we should inherit.
5043f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis            if ((cb_node->createInfo.level != VK_COMMAND_BUFFER_LEVEL_PRIMARY) &&
5044f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis                (cb_node->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT)) {
50459a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                cb_node->activeRenderPass = GetRenderPassState(dev_data, cb_node->beginInfo.pInheritanceInfo->renderPass);
5046f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis                cb_node->activeSubpass = cb_node->beginInfo.pInheritanceInfo->subpass;
5047350841afb70bf8dcfc3c6ec6b66f0aaa639553a3Tobin Ehlis                cb_node->activeFramebuffer = cb_node->beginInfo.pInheritanceInfo->framebuffer;
5048f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis                cb_node->framebuffers.insert(cb_node->beginInfo.pInheritanceInfo->framebuffer);
5049888e1d268098177fde4a2263e3d7b7cc415f1debMark Young            }
50505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
50515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
5052b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
50533251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (skip) {
50545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return VK_ERROR_VALIDATION_FAILED_EXT;
50555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
50564a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.BeginCommandBuffer(commandBuffer, pBeginInfo);
5057400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis
50585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
50595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
50605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
506189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL EndCommandBuffer(VkCommandBuffer commandBuffer) {
50623251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
506356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
5064ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
50659a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer);
50665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
50674527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton        if ((VK_COMMAND_BUFFER_LEVEL_PRIMARY == pCB->createInfo.level) ||
50684527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton            !(pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT)) {
5069fd61966f8d41b5bce15620b70563b7864cbb28feCody Northrop            // This needs spec clarification to update valid usage, see comments in PR:
5070fd61966f8d41b5bce15620b70563b7864cbb28feCody Northrop            // https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/pull/516#discussion_r63013756
5071315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis            skip |= insideRenderPass(dev_data, pCB, "vkEndCommandBuffer()", VALIDATION_ERROR_27400078);
5072fd61966f8d41b5bce15620b70563b7864cbb28feCody Northrop        }
50733251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateCmd(dev_data, pCB, CMD_END, "vkEndCommandBuffer()");
50745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (auto query : pCB->activeQueries) {
50753251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
5076315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_2740007a, "DS",
50773251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "Ending command buffer with in progress query: queryPool 0x%" PRIx64 ", index %d. %s",
5078315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(query.pool), query.index, validation_error_map[VALIDATION_ERROR_2740007a]);
50795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
50805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
50813251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (!skip) {
5082b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.unlock();
50830d9453d85335963d6cabfbf400b058dc905ea238Chris Forbes        auto result = dev_data->dispatch_table.EndCommandBuffer(commandBuffer);
5084b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.lock();
50855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (VK_SUCCESS == result) {
50865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            pCB->state = CB_RECORDED;
50875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
50880d9453d85335963d6cabfbf400b058dc905ea238Chris Forbes        return result;
50895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    } else {
50900d9453d85335963d6cabfbf400b058dc905ea238Chris Forbes        return VK_ERROR_VALIDATION_FAILED_EXT;
50915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
50925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
50935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5094bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL ResetCommandBuffer(VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags) {
50953251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
509656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
5097ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
50989a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer);
50995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    VkCommandPool cmdPool = pCB->createInfo.commandPool;
51009a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto pPool = GetCommandPoolNode(dev_data, cmdPool);
5101cd9a648074f67a1d44c15a056b90fc66da8ead17Chris Forbes    if (!(VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT & pPool->createFlags)) {
51023251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
5103315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_3260005c, "DS",
51043251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "Attempt to reset command buffer (0x%p) created from command pool (0x%" PRIxLEAST64
51053251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        ") that does NOT have the VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT bit set. %s",
5106315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        commandBuffer, HandleToUint64(cmdPool), validation_error_map[VALIDATION_ERROR_3260005c]);
51075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
5108315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis    skip |= checkCommandBufferInFlight(dev_data, pCB, "reset", VALIDATION_ERROR_3260005a);
5109b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
51103251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
51114a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.ResetCommandBuffer(commandBuffer, flags);
51125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
5113b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.lock();
51145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        resetCB(dev_data, commandBuffer);
5115b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.unlock();
51165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
51175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
51185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
511993c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski
5120bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBindPipeline(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint,
5121bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                           VkPipeline pipeline) {
5122e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis    bool skip = false;
512356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
5124ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
51259a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer);
5126e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis    if (cb_state) {
5127baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt        skip |= ValidateCmdQueueFlags(dev_data, cb_state, "vkCmdBindPipeline()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT,
5128315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                      VALIDATION_ERROR_18002415);
512929f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis        skip |= ValidateCmd(dev_data, cb_state, CMD_BINDPIPELINE, "vkCmdBindPipeline()");
5130e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis        if ((VK_PIPELINE_BIND_POINT_COMPUTE == pipelineBindPoint) && (cb_state->activeRenderPass)) {
5131e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis            skip |=
51325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
51339b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        HandleToUint64(pipeline), __LINE__, DRAWSTATE_INVALID_RENDERPASS_CMD, "DS",
5134414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                        "Incorrectly binding compute pipeline (0x%" PRIxLEAST64 ") during active RenderPass (0x%" PRIxLEAST64 ")",
51359b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        HandleToUint64(pipeline), HandleToUint64(cb_state->activeRenderPass->renderPass));
51365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
5137315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        // TODO: VALIDATION_ERROR_18000612 VALIDATION_ERROR_18000616
51385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5139e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis        PIPELINE_STATE *pipe_state = getPipelineState(dev_data, pipeline);
5140e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis        if (pipe_state) {
5141e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis            cb_state->lastBound[pipelineBindPoint].pipeline_state = pipe_state;
5142e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis            set_cb_pso_status(cb_state, pipe_state);
5143e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis            set_pipeline_state(pipe_state);
5144daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski            skip |= validate_dual_src_blend_feature(dev_data, pipe_state);
51455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else {
5146e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
5147315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(pipeline), __LINE__, VALIDATION_ERROR_18027e01, "DS",
51489b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            "Attempt to bind Pipeline 0x%" PRIxLEAST64 " that doesn't exist! %s", HandleToUint64(pipeline),
5149315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            validation_error_map[VALIDATION_ERROR_18027e01]);
5150e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis        }
51519b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus        addCommandBufferBinding(&pipe_state->cb_bindings, {HandleToUint64(pipeline), kVulkanObjectTypePipeline}, cb_state);
5152e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis        if (VK_PIPELINE_BIND_POINT_GRAPHICS == pipelineBindPoint) {
5153e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis            // Add binding for child renderpass
51549a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            auto rp_state = GetRenderPassState(dev_data, pipe_state->graphicsPipelineCI.renderPass);
5155e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis            if (rp_state) {
51569b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                addCommandBufferBinding(&rp_state->cb_bindings, {HandleToUint64(rp_state->renderPass), kVulkanObjectTypeRenderPass},
51579b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                        cb_state);
5158e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis            }
51595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
51605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
5161b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
5162cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (!skip) dev_data->dispatch_table.CmdBindPipeline(commandBuffer, pipelineBindPoint, pipeline);
51635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
51645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5165bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetViewport(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount,
5166bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                          const VkViewport *pViewports) {
51673251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
516856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
5169ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
51709a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer);
51715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
5172315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetViewport()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_1e002415);
51733251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateCmd(dev_data, pCB, CMD_SETVIEWPORTSTATE, "vkCmdSetViewport()");
5174bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        pCB->viewportMask |= ((1u << viewportCount) - 1u) << firstViewport;
51755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
5176b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
51773251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (!skip) dev_data->dispatch_table.CmdSetViewport(commandBuffer, firstViewport, viewportCount, pViewports);
51785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
51795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5180bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetScissor(VkCommandBuffer commandBuffer, uint32_t firstScissor, uint32_t scissorCount,
5181bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                         const VkRect2D *pScissors) {
51823251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
518356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
5184ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
51859a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer);
51865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
5187315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetScissor()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_1d802415);
51883251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateCmd(dev_data, pCB, CMD_SETSCISSORSTATE, "vkCmdSetScissor()");
5189bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        pCB->scissorMask |= ((1u << scissorCount) - 1u) << firstScissor;
51905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
5191b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
51923251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (!skip) dev_data->dispatch_table.CmdSetScissor(commandBuffer, firstScissor, scissorCount, pScissors);
51935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
51945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
519589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdSetLineWidth(VkCommandBuffer commandBuffer, float lineWidth) {
51963251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
519756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
5198ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
51999a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer);
52005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
5201315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetLineWidth()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_1d602415);
52023251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateCmd(dev_data, pCB, CMD_SETLINEWIDTHSTATE, "vkCmdSetLineWidth()");
52035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->status |= CBSTATUS_LINE_WIDTH_SET;
5204a27508babf63d50aea75883a3702979193c23683Mark Young
52054c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis        PIPELINE_STATE *pPipeTrav = pCB->lastBound[VK_PIPELINE_BIND_POINT_GRAPHICS].pipeline_state;
5206a27508babf63d50aea75883a3702979193c23683Mark Young        if (pPipeTrav != NULL && !isDynamic(pPipeTrav, VK_DYNAMIC_STATE_LINE_WIDTH)) {
52073251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
5208315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_1d600626, "DS",
52093251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "vkCmdSetLineWidth called but pipeline was created without VK_DYNAMIC_STATE_LINE_WIDTH "
52103251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "flag.  This is undefined behavior and could be ignored. %s",
5211315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            validation_error_map[VALIDATION_ERROR_1d600626]);
5212a27508babf63d50aea75883a3702979193c23683Mark Young        } else {
52139b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus            skip |= verifyLineWidth(dev_data, DRAWSTATE_INVALID_SET, kVulkanObjectTypeCommandBuffer, HandleToUint64(commandBuffer),
52149b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                    lineWidth);
5215a27508babf63d50aea75883a3702979193c23683Mark Young        }
52165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
5217b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
52183251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (!skip) dev_data->dispatch_table.CmdSetLineWidth(commandBuffer, lineWidth);
52195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
52205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5221bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetDepthBias(VkCommandBuffer commandBuffer, float depthBiasConstantFactor, float depthBiasClamp,
5222bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                           float depthBiasSlopeFactor) {
52233251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
522456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
5225ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
52269a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer);
52275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
5228315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetDepthBias()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_1cc02415);
52293251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateCmd(dev_data, pCB, CMD_SETDEPTHBIASSTATE, "vkCmdSetDepthBias()");
5230434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski        if ((depthBiasClamp != 0.0) && (!dev_data->enabled_features.depthBiasClamp)) {
52313251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
5232315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_1cc0062c, "DS",
52333251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "vkCmdSetDepthBias(): the depthBiasClamp device feature is disabled: the depthBiasClamp "
52343251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "parameter must be set to 0.0. %s",
5235315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            validation_error_map[VALIDATION_ERROR_1cc0062c]);
5236434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski        }
52373251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        if (!skip) {
5238434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski            pCB->status |= CBSTATUS_DEPTH_BIAS_SET;
5239434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski        }
52405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
5241b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
52423251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (!skip)
52434a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdSetDepthBias(commandBuffer, depthBiasConstantFactor, depthBiasClamp, depthBiasSlopeFactor);
52445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
52455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
524689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdSetBlendConstants(VkCommandBuffer commandBuffer, const float blendConstants[4]) {
52473251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
524856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
5249ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
52509a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer);
52515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
5252315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetBlendConstants()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_1ca02415);
52533251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateCmd(dev_data, pCB, CMD_SETBLENDSTATE, "vkCmdSetBlendConstants()");
52543d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis        pCB->status |= CBSTATUS_BLEND_CONSTANTS_SET;
52555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
5256b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
52573251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (!skip) dev_data->dispatch_table.CmdSetBlendConstants(commandBuffer, blendConstants);
52585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
52595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5260bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetDepthBounds(VkCommandBuffer commandBuffer, float minDepthBounds, float maxDepthBounds) {
52613251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
526256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
5263ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
52649a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer);
52655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
5266315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetDepthBounds()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_1ce02415);
52673251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateCmd(dev_data, pCB, CMD_SETDEPTHBOUNDSSTATE, "vkCmdSetDepthBounds()");
52685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->status |= CBSTATUS_DEPTH_BOUNDS_SET;
52695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
5270b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
52713251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (!skip) dev_data->dispatch_table.CmdSetDepthBounds(commandBuffer, minDepthBounds, maxDepthBounds);
52725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
52735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5274bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetStencilCompareMask(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask,
5275bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                    uint32_t compareMask) {
52763251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
527756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
5278ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
52799a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer);
52805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
5281315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |=
5282315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis            ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetStencilCompareMask()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_1da02415);
52833251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateCmd(dev_data, pCB, CMD_SETSTENCILREADMASKSTATE, "vkCmdSetStencilCompareMask()");
52845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->status |= CBSTATUS_STENCIL_READ_MASK_SET;
52855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
5286b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
52873251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (!skip) dev_data->dispatch_table.CmdSetStencilCompareMask(commandBuffer, faceMask, compareMask);
52885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
52895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5290bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetStencilWriteMask(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t writeMask) {
52913251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
529256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
5293ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
52949a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer);
52955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
5296315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |=
5297315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis            ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetStencilWriteMask()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_1de02415);
52983251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateCmd(dev_data, pCB, CMD_SETSTENCILWRITEMASKSTATE, "vkCmdSetStencilWriteMask()");
52995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->status |= CBSTATUS_STENCIL_WRITE_MASK_SET;
53005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
5301b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
53023251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (!skip) dev_data->dispatch_table.CmdSetStencilWriteMask(commandBuffer, faceMask, writeMask);
53035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
53045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5305bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetStencilReference(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t reference) {
53063251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
530756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
5308ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
53099a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer);
53105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
5311315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |=
5312315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis            ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetStencilReference()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_1dc02415);
53133251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateCmd(dev_data, pCB, CMD_SETSTENCILREFERENCESTATE, "vkCmdSetStencilReference()");
53145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->status |= CBSTATUS_STENCIL_REFERENCE_SET;
53155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
5316b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
53173251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (!skip) dev_data->dispatch_table.CmdSetStencilReference(commandBuffer, faceMask, reference);
53185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
53195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5320bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBindDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint,
5321bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                 VkPipelineLayout layout, uint32_t firstSet, uint32_t setCount,
5322bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                 const VkDescriptorSet *pDescriptorSets, uint32_t dynamicOffsetCount,
5323bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                 const uint32_t *pDynamicOffsets) {
5324946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski    bool skip = false;
532556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
5326ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
5327946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski    GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer);
5328946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski    if (cb_state) {
5329baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt        skip |= ValidateCmdQueueFlags(dev_data, cb_state, "vkCmdBindDescriptorSets()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT,
5330315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                      VALIDATION_ERROR_17c02415);
5331946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski        skip |= ValidateCmd(dev_data, cb_state, CMD_BINDDESCRIPTORSETS, "vkCmdBindDescriptorSets()");
5332ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski        // Track total count of dynamic descriptor types to make sure we have an offset for each one
5333946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski        uint32_t total_dynamic_descriptors = 0;
5334946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski        string error_string = "";
5335946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski        uint32_t last_set_index = firstSet + setCount - 1;
5336946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski        if (last_set_index >= cb_state->lastBound[pipelineBindPoint].boundDescriptorSets.size()) {
5337946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski            cb_state->lastBound[pipelineBindPoint].boundDescriptorSets.resize(last_set_index + 1);
5338946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski            cb_state->lastBound[pipelineBindPoint].dynamicOffsets.resize(last_set_index + 1);
5339946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski        }
5340946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski        auto old_final_bound_set = cb_state->lastBound[pipelineBindPoint].boundDescriptorSets[last_set_index];
5341ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski        auto pipeline_layout = getPipelineLayout(dev_data, layout);
5342ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski        for (uint32_t set_idx = 0; set_idx < setCount; set_idx++) {
5343ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski            cvdescriptorset::DescriptorSet *descriptor_set = GetSetNode(dev_data, pDescriptorSets[set_idx]);
5344ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski            if (descriptor_set) {
5345946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski                cb_state->lastBound[pipelineBindPoint].pipeline_layout = *pipeline_layout;
5346946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski                cb_state->lastBound[pipelineBindPoint].boundDescriptorSets[set_idx + firstSet] = descriptor_set;
5347ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski                if (!descriptor_set->IsUpdated() && (descriptor_set->GetTotalDescriptorCount() != 0)) {
5348946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski                    skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT,
53499b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                    VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, HandleToUint64(pDescriptorSets[set_idx]),
53509b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                    __LINE__, DRAWSTATE_DESCRIPTOR_SET_NOT_UPDATED, "DS",
5351946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski                                    "Descriptor Set 0x%" PRIxLEAST64
5352946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski                                    " bound but it was never updated. You may want to either update it or not bind it.",
53539b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                    HandleToUint64(pDescriptorSets[set_idx]));
5354ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski                }
5355ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski                // Verify that set being bound is compatible with overlapping setLayout of pipelineLayout
535612b7fc342b53fbdd399aae4a85959e37685936acChris Forbes                if (!verify_set_layout_compatibility(descriptor_set, pipeline_layout, set_idx + firstSet, error_string)) {
5357946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski                    skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
53589b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                    VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, HandleToUint64(pDescriptorSets[set_idx]),
5359315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    __LINE__, VALIDATION_ERROR_17c002cc, "DS",
5360946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski                                    "descriptorSet #%u being bound is not compatible with overlapping descriptorSetLayout "
5361946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski                                    "at index %u of pipelineLayout 0x%" PRIxLEAST64 " due to: %s. %s",
53629b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                    set_idx, set_idx + firstSet, HandleToUint64(layout), error_string.c_str(),
5363315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    validation_error_map[VALIDATION_ERROR_17c002cc]);
53645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
5365ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski
5366946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski                auto set_dynamic_descriptor_count = descriptor_set->GetDynamicDescriptorCount();
5367ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski
5368946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski                cb_state->lastBound[pipelineBindPoint].dynamicOffsets[firstSet + set_idx].clear();
5369ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski
5370946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski                if (set_dynamic_descriptor_count) {
5371ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski                    // First make sure we won't overstep bounds of pDynamicOffsets array
5372946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski                    if ((total_dynamic_descriptors + set_dynamic_descriptor_count) > dynamicOffsetCount) {
53739b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        skip |= log_msg(
53749b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
53759b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(pDescriptorSets[set_idx]), __LINE__, DRAWSTATE_INVALID_DYNAMIC_OFFSET_COUNT, "DS",
53769b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            "descriptorSet #%u (0x%" PRIxLEAST64
53779b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            ") requires %u dynamicOffsets, but only %u dynamicOffsets are left in pDynamicOffsets "
53789b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            "array. There must be one dynamic offset for each dynamic descriptor being bound.",
53799b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            set_idx, HandleToUint64(pDescriptorSets[set_idx]), descriptor_set->GetDynamicDescriptorCount(),
53809b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            (dynamicOffsetCount - total_dynamic_descriptors));
5381ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski                    } else {  // Validate and store dynamic offsets with the set
5382ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski                        // Validate Dynamic Offset Minimums
5383946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski                        uint32_t cur_dyn_offset = total_dynamic_descriptors;
5384ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski                        for (uint32_t d = 0; d < descriptor_set->GetTotalDescriptorCount(); d++) {
5385ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski                            if (descriptor_set->GetTypeFromGlobalIndex(d) == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) {
538616769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton                                if (SafeModulo(
5387ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski                                        pDynamicOffsets[cur_dyn_offset],
5388ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski                                        dev_data->phys_dev_properties.properties.limits.minUniformBufferOffsetAlignment) != 0) {
5389315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    skip |=
5390315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                        log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
5391315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                                VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__,
5392315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                                VALIDATION_ERROR_17c002d4, "DS",
5393315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                                "vkCmdBindDescriptorSets(): pDynamicOffsets[%d] is %d but must be a multiple of "
5394315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                                "device limit minUniformBufferOffsetAlignment 0x%" PRIxLEAST64 ". %s",
5395315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                                cur_dyn_offset, pDynamicOffsets[cur_dyn_offset],
5396315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                                dev_data->phys_dev_properties.properties.limits.minUniformBufferOffsetAlignment,
5397315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                                validation_error_map[VALIDATION_ERROR_17c002d4]);
5398ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski                                }
5399ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski                                cur_dyn_offset++;
5400ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski                            } else if (descriptor_set->GetTypeFromGlobalIndex(d) == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) {
540116769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton                                if (SafeModulo(
5402ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski                                        pDynamicOffsets[cur_dyn_offset],
5403ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski                                        dev_data->phys_dev_properties.properties.limits.minStorageBufferOffsetAlignment) != 0) {
5404315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    skip |=
5405315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                        log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
5406315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                                VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__,
5407315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                                VALIDATION_ERROR_17c002d4, "DS",
5408315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                                "vkCmdBindDescriptorSets(): pDynamicOffsets[%d] is %d but must be a multiple of "
5409315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                                "device limit minStorageBufferOffsetAlignment 0x%" PRIxLEAST64 ". %s",
5410315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                                cur_dyn_offset, pDynamicOffsets[cur_dyn_offset],
5411315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                                dev_data->phys_dev_properties.properties.limits.minStorageBufferOffsetAlignment,
5412315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                                validation_error_map[VALIDATION_ERROR_17c002d4]);
5413ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski                                }
5414ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski                                cur_dyn_offset++;
5415ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski                            }
541672d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis                        }
5417ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski
5418946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski                        cb_state->lastBound[pipelineBindPoint].dynamicOffsets[firstSet + set_idx] =
5419946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski                            std::vector<uint32_t>(pDynamicOffsets + total_dynamic_descriptors,
5420946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski                                                  pDynamicOffsets + total_dynamic_descriptors + set_dynamic_descriptor_count);
5421ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski                        // Keep running total of dynamic descriptor count to verify at the end
5422946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski                        total_dynamic_descriptors += set_dynamic_descriptor_count;
542372d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis                    }
542472d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis                }
5425ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski            } else {
54269b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                skip |=
54279b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
54289b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(pDescriptorSets[set_idx]), __LINE__, DRAWSTATE_INVALID_SET, "DS",
54299b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            "Attempt to bind descriptor set 0x%" PRIxLEAST64 " that doesn't exist!",
54309b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(pDescriptorSets[set_idx]));
5431ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski            }
5432ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski            // For any previously bound sets, need to set them to "invalid" if they were disturbed by this update
5433ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski            if (firstSet > 0) {  // Check set #s below the first bound set
5434ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski                for (uint32_t i = 0; i < firstSet; ++i) {
5435946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski                    if (cb_state->lastBound[pipelineBindPoint].boundDescriptorSets[i] &&
543612b7fc342b53fbdd399aae4a85959e37685936acChris Forbes                        !verify_set_layout_compatibility(cb_state->lastBound[pipelineBindPoint].boundDescriptorSets[i],
5437946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski                                                         pipeline_layout, i, error_string)) {
5438946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski                        skip |= log_msg(
5439ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski                            dev_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT,
5440ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski                            VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
54419b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(cb_state->lastBound[pipelineBindPoint].boundDescriptorSets[i]), __LINE__, DRAWSTATE_NONE,
54429b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            "DS", "DescriptorSet 0x%" PRIxLEAST64
54439b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                  " previously bound as set #%u was disturbed by newly bound pipelineLayout (0x%" PRIxLEAST64 ")",
54449b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(cb_state->lastBound[pipelineBindPoint].boundDescriptorSets[i]), i,
54459b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(layout));
5446946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski                        cb_state->lastBound[pipelineBindPoint].boundDescriptorSets[i] = VK_NULL_HANDLE;
54475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    }
54485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
54495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
5450ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski            // Check if newly last bound set invalidates any remaining bound sets
5451946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski            if ((cb_state->lastBound[pipelineBindPoint].boundDescriptorSets.size() - 1) > (last_set_index)) {
5452946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski                if (old_final_bound_set &&
545312b7fc342b53fbdd399aae4a85959e37685936acChris Forbes                    !verify_set_layout_compatibility(old_final_bound_set, pipeline_layout, last_set_index, error_string)) {
5454946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski                    auto old_set = old_final_bound_set->GetSet();
5455946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski                    skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT,
54569b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                    VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, HandleToUint64(old_set), __LINE__,
5457946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski                                    DRAWSTATE_NONE, "DS", "DescriptorSet 0x%" PRIxLEAST64
5458946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski                                                          " previously bound as set #%u is incompatible with set 0x%" PRIxLEAST64
5459946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski                                                          " newly bound as set #%u so set #%u and any subsequent sets were "
5460946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski                                                          "disturbed by newly bound pipelineLayout (0x%" PRIxLEAST64 ")",
54619b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                    HandleToUint64(old_set), last_set_index,
54629b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                    HandleToUint64(cb_state->lastBound[pipelineBindPoint].boundDescriptorSets[last_set_index]),
54639b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                    last_set_index, last_set_index + 1, HandleToUint64(layout));
5464946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski                    cb_state->lastBound[pipelineBindPoint].boundDescriptorSets.resize(last_set_index + 1);
5465ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski                }
5466787f29d93dee194c015789cf61c079504c980572Tobin Ehlis            }
5467ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski        }
5468ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski        //  dynamicOffsetCount must equal the total number of dynamic descriptors in the sets being bound
5469946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski        if (total_dynamic_descriptors != dynamicOffsetCount) {
5470315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis            skip |=
5471315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
5472315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_17c002ce, "DS",
5473315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        "Attempting to bind %u descriptorSets with %u dynamic descriptors, but dynamicOffsetCount "
5474315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        "is %u. It should exactly match the number of dynamic descriptors. %s",
5475315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        setCount, total_dynamic_descriptors, dynamicOffsetCount, validation_error_map[VALIDATION_ERROR_17c002ce]);
54765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
54775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
5478b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
5479946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski    if (!skip)
54804a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdBindDescriptorSets(commandBuffer, pipelineBindPoint, layout, firstSet, setCount,
54814a0754042cf090e131e9e769d8a3633c228625beChris Forbes                                                       pDescriptorSets, dynamicOffsetCount, pDynamicOffsets);
54825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
54835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5484bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBindIndexBuffer(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
5485bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                              VkIndexType indexType) {
5486946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski    bool skip = false;
548756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
5488593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis    // TODO : Somewhere need to verify that IBs have correct usage state flagged
5489ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
5490b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski
54919a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto buffer_state = GetBufferState(dev_data, buffer);
54929a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto cb_node = GetCBNode(dev_data, commandBuffer);
54935cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis    if (cb_node && buffer_state) {
5494315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |=
5495315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis            ValidateCmdQueueFlags(dev_data, cb_node, "vkCmdBindIndexBuffer()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_17e02415);
5496946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski        skip |= ValidateCmd(dev_data, cb_node, CMD_BINDINDEXBUFFER, "vkCmdBindIndexBuffer()");
5497315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= ValidateMemoryIsBoundToBuffer(dev_data, buffer_state, "vkCmdBindIndexBuffer()", VALIDATION_ERROR_17e00364);
5498ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski        std::function<bool()> function = [=]() {
5499ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski            return ValidateBufferMemoryIsValid(dev_data, buffer_state, "vkCmdBindIndexBuffer()");
5500ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski        };
5501ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski        cb_node->validate_functions.push_back(function);
5502ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski        VkDeviceSize offset_align = 0;
5503ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski        switch (indexType) {
5504ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski            case VK_INDEX_TYPE_UINT16:
5505ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski                offset_align = 2;
5506ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski                break;
5507ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski            case VK_INDEX_TYPE_UINT32:
5508ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski                offset_align = 4;
5509ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski                break;
5510ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski            default:
5511ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski                // ParamChecker should catch bad enum, we'll also throw alignment error below if offset_align stays 0
5512ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski                break;
55135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
5514ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski        if (!offset_align || (offset % offset_align)) {
5515df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
55169b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(commandBuffer), __LINE__, DRAWSTATE_VTX_INDEX_ALIGNMENT_ERROR, "DS",
5517946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski                            "vkCmdBindIndexBuffer() offset (0x%" PRIxLEAST64 ") does not fall on alignment (%s) boundary.", offset,
5518946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski                            string_VkIndexType(indexType));
5519ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski        }
5520ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski        cb_node->status |= CBSTATUS_INDEX_BUFFER_BOUND;
5521ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    } else {
5522ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        assert(0);
55235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
5524b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
5525946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski    if (!skip) dev_data->dispatch_table.CmdBindIndexBuffer(commandBuffer, buffer, offset, indexType);
55265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
55275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
55285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisvoid updateResourceTracking(GLOBAL_CB_NODE *pCB, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer *pBuffers) {
55295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    uint32_t end = firstBinding + bindingCount;
55305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB->currentDrawData.buffers.size() < end) {
55315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->currentDrawData.buffers.resize(end);
55325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
55335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < bindingCount; ++i) {
55345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->currentDrawData.buffers[i + firstBinding] = pBuffers[i];
55355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
55365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
55375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5538e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic inline void updateResourceTrackingOnDraw(GLOBAL_CB_NODE *pCB) { pCB->drawData.push_back(pCB->currentDrawData); }
55395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5540bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBindVertexBuffers(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount,
5541bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                const VkBuffer *pBuffers, const VkDeviceSize *pOffsets) {
5542946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski    bool skip = false;
554356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
5544593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis    // TODO : Somewhere need to verify that VBs have correct usage state flagged
5545ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
5546b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski
55479a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto cb_node = GetCBNode(dev_data, commandBuffer);
55489f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis    if (cb_node) {
5549315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |=
5550315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis            ValidateCmdQueueFlags(dev_data, cb_node, "vkCmdBindVertexBuffers()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_18202415);
5551baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt        skip |= ValidateCmd(dev_data, cb_node, CMD_BINDVERTEXBUFFER, "vkCmdBindVertexBuffers()");
5552ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski        for (uint32_t i = 0; i < bindingCount; ++i) {
5553ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski            auto buffer_state = GetBufferState(dev_data, pBuffers[i]);
5554ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski            assert(buffer_state);
5555315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis            skip |= ValidateMemoryIsBoundToBuffer(dev_data, buffer_state, "vkCmdBindVertexBuffers()", VALIDATION_ERROR_182004e8);
5556ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski            std::function<bool()> function = [=]() {
5557ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski                return ValidateBufferMemoryIsValid(dev_data, buffer_state, "vkCmdBindVertexBuffers()");
5558ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski            };
5559ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski            cb_node->validate_functions.push_back(function);
55605fe7f75f980a78c0179ff93438d8786e6cb44b20Tony Barbour            if (pOffsets[i] >= buffer_state->createInfo.size) {
55615fe7f75f980a78c0179ff93438d8786e6cb44b20Tony Barbour                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT,
5562315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                HandleToUint64(buffer_state->buffer), __LINE__, VALIDATION_ERROR_182004e4, "DS",
55635fe7f75f980a78c0179ff93438d8786e6cb44b20Tony Barbour                                "vkCmdBindVertexBuffers() offset (0x%" PRIxLEAST64 ") is beyond the end of the buffer. %s",
5564315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                pOffsets[i], validation_error_map[VALIDATION_ERROR_182004e4]);
55655fe7f75f980a78c0179ff93438d8786e6cb44b20Tony Barbour            }
55665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
5567ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski        updateResourceTracking(cb_node, firstBinding, bindingCount, pBuffers);
55685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    } else {
55697828015969ab31ee01d597f0288cbb124b637fcdMark Lobodzinski        assert(0);
55705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
5571b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
5572946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski    if (!skip) dev_data->dispatch_table.CmdBindVertexBuffers(commandBuffer, firstBinding, bindingCount, pBuffers, pOffsets);
55735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
55745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
557525002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// Expects global_lock to be held by caller
55765569d6457ac22e7d245f3cdee045e71ffbc8b06eTobin Ehlisstatic void MarkStoreImagesAndBuffersAsWritten(layer_data *dev_data, GLOBAL_CB_NODE *pCB) {
55777a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis    for (auto imageView : pCB->updateImages) {
55789a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto view_state = GetImageViewState(dev_data, imageView);
5579cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        if (!view_state) continue;
5580249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis
55819a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto image_state = GetImageState(dev_data, view_state->create_info.image);
55821facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis        assert(image_state);
5583e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves        std::function<bool()> function = [=]() {
55841facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis            SetImageMemoryValid(dev_data, image_state, true);
5585e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves            return false;
55867a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis        };
55877a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis        pCB->validate_functions.push_back(function);
55887a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis    }
55897a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis    for (auto buffer : pCB->updateBuffers) {
55909a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto buffer_state = GetBufferState(dev_data, buffer);
55915cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis        assert(buffer_state);
5592e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves        std::function<bool()> function = [=]() {
55935cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis            SetBufferMemoryValid(dev_data, buffer_state, true);
5594e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves            return false;
55957a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis        };
55967a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis        pCB->validate_functions.push_back(function);
55975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
55985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
55995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5600ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis// Generic function to handle validation for all CmdDraw* type functions
5601ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool ValidateCmdDrawType(layer_data *dev_data, VkCommandBuffer cmd_buffer, bool indexed, VkPipelineBindPoint bind_point,
5602baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt                                CMD_TYPE cmd_type, GLOBAL_CB_NODE **cb_state, const char *caller, VkQueueFlags queue_flags,
5603baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt                                UNIQUE_VALIDATION_ERROR_CODE queue_flag_code, UNIQUE_VALIDATION_ERROR_CODE msg_code,
5604baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt                                UNIQUE_VALIDATION_ERROR_CODE const dynamic_state_msg_code) {
560558b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis    bool skip = false;
56069a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    *cb_state = GetCBNode(dev_data, cmd_buffer);
560758b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis    if (*cb_state) {
5608baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt        skip |= ValidateCmdQueueFlags(dev_data, *cb_state, caller, queue_flags, queue_flag_code);
5609ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis        skip |= ValidateCmd(dev_data, *cb_state, cmd_type, caller);
56104f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes        skip |= ValidateDrawState(dev_data, *cb_state, indexed, bind_point, caller, dynamic_state_msg_code);
561125d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis        skip |= (VK_PIPELINE_BIND_POINT_GRAPHICS == bind_point) ? outsideRenderPass(dev_data, *cb_state, caller, msg_code)
561225d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis                                                                : insideRenderPass(dev_data, *cb_state, caller, msg_code);
561358b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis    }
561458b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis    return skip;
561558b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis}
561658b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis
561725d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis// Generic function to handle state update for all CmdDraw* and CmdDispatch* type functions
56186b33c4e6a6f232fca84e0a6229106717b0012488Chris Forbesstatic void UpdateStateCmdDrawDispatchType(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point) {
5619ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis    UpdateDrawState(dev_data, cb_state, bind_point);
56202f921d33544c162dcb726fc3c7b915e89c02ff24Tobin Ehlis    MarkStoreImagesAndBuffersAsWritten(dev_data, cb_state);
562125d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis}
562225d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis
5623ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis// Generic function to handle state update for all CmdDraw* type functions
56246b33c4e6a6f232fca84e0a6229106717b0012488Chris Forbesstatic void UpdateStateCmdDrawType(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point) {
56256b33c4e6a6f232fca84e0a6229106717b0012488Chris Forbes    UpdateStateCmdDrawDispatchType(dev_data, cb_state, bind_point);
5626c0b225e42808ba8fada7a2f67ecd662e376ccf15Tobin Ehlis    updateResourceTrackingOnDraw(cb_state);
5627b68b13ed4952bce61f6ebb0023542660c26b0562Chris Forbes    cb_state->hasDrawCmd = true;
5628ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis}
5629ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis
5630ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool PreCallValidateCmdDraw(layer_data *dev_data, VkCommandBuffer cmd_buffer, bool indexed, VkPipelineBindPoint bind_point,
5631ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis                                   GLOBAL_CB_NODE **cb_state, const char *caller) {
5632baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt    return ValidateCmdDrawType(dev_data, cmd_buffer, indexed, bind_point, CMD_DRAW, cb_state, caller, VK_QUEUE_GRAPHICS_BIT,
5633315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                               VALIDATION_ERROR_1a202415, VALIDATION_ERROR_1a200017, VALIDATION_ERROR_1a200376);
5634ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis}
5635ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis
5636ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void PostCallRecordCmdDraw(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point) {
56376b33c4e6a6f232fca84e0a6229106717b0012488Chris Forbes    UpdateStateCmdDrawType(dev_data, cb_state, bind_point);
5638c0b225e42808ba8fada7a2f67ecd662e376ccf15Tobin Ehlis}
5639c0b225e42808ba8fada7a2f67ecd662e376ccf15Tobin Ehlis
564089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount,
564189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                   uint32_t firstVertex, uint32_t firstInstance) {
564256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
564358b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis    GLOBAL_CB_NODE *cb_state = nullptr;
5644ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
5645ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis    bool skip = PreCallValidateCmdDraw(dev_data, commandBuffer, false, VK_PIPELINE_BIND_POINT_GRAPHICS, &cb_state, "vkCmdDraw()");
5646b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
564758b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis    if (!skip) {
56484a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdDraw(commandBuffer, vertexCount, instanceCount, firstVertex, firstInstance);
5649c0b225e42808ba8fada7a2f67ecd662e376ccf15Tobin Ehlis        lock.lock();
5650ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis        PostCallRecordCmdDraw(dev_data, cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS);
5651c0b225e42808ba8fada7a2f67ecd662e376ccf15Tobin Ehlis        lock.unlock();
5652c0b225e42808ba8fada7a2f67ecd662e376ccf15Tobin Ehlis    }
56535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
56545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5655ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool PreCallValidateCmdDrawIndexed(layer_data *dev_data, VkCommandBuffer cmd_buffer, bool indexed,
5656ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis                                          VkPipelineBindPoint bind_point, GLOBAL_CB_NODE **cb_state, const char *caller) {
5657baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt    return ValidateCmdDrawType(dev_data, cmd_buffer, indexed, bind_point, CMD_DRAWINDEXED, cb_state, caller, VK_QUEUE_GRAPHICS_BIT,
5658315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                               VALIDATION_ERROR_1a402415, VALIDATION_ERROR_1a400017, VALIDATION_ERROR_1a40039c);
5659ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis}
5660ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis
5661ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void PostCallRecordCmdDrawIndexed(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point) {
56626b33c4e6a6f232fca84e0a6229106717b0012488Chris Forbes    UpdateStateCmdDrawType(dev_data, cb_state, bind_point);
5663ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis}
5664ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis
5665bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount,
5666bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                          uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance) {
566756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
5668ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis    GLOBAL_CB_NODE *cb_state = nullptr;
5669ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
5670ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis    bool skip = PreCallValidateCmdDrawIndexed(dev_data, commandBuffer, true, VK_PIPELINE_BIND_POINT_GRAPHICS, &cb_state,
5671ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis                                              "vkCmdDrawIndexed()");
5672b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
5673ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis    if (!skip) {
56744a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdDrawIndexed(commandBuffer, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
5675ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis        lock.lock();
5676ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis        PostCallRecordCmdDrawIndexed(dev_data, cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS);
5677ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis        lock.unlock();
5678ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis    }
56795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
56805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5681ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool PreCallValidateCmdDrawIndirect(layer_data *dev_data, VkCommandBuffer cmd_buffer, VkBuffer buffer, bool indexed,
5682ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis                                           VkPipelineBindPoint bind_point, GLOBAL_CB_NODE **cb_state, BUFFER_STATE **buffer_state,
5683ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis                                           const char *caller) {
5684315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis    bool skip =
5685315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        ValidateCmdDrawType(dev_data, cmd_buffer, indexed, bind_point, CMD_DRAWINDIRECT, cb_state, caller, VK_QUEUE_GRAPHICS_BIT,
5686315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            VALIDATION_ERROR_1aa02415, VALIDATION_ERROR_1aa00017, VALIDATION_ERROR_1aa003cc);
56879a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    *buffer_state = GetBufferState(dev_data, buffer);
5688315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis    skip |= ValidateMemoryIsBoundToBuffer(dev_data, *buffer_state, caller, VALIDATION_ERROR_1aa003b4);
568913c4316d0072cbc5bf3cd729abef4d114f3c96edMark Lobodzinski    // TODO: If the drawIndirectFirstInstance feature is not enabled, all the firstInstance members of the
569013c4316d0072cbc5bf3cd729abef4d114f3c96edMark Lobodzinski    // VkDrawIndirectCommand structures accessed by this command must be 0, which will require access to the contents of 'buffer'.
5691d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis    return skip;
5692d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis}
5693d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis
5694ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void PostCallRecordCmdDrawIndirect(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point,
5695ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis                                          BUFFER_STATE *buffer_state) {
56966b33c4e6a6f232fca84e0a6229106717b0012488Chris Forbes    UpdateStateCmdDrawType(dev_data, cb_state, bind_point);
5697d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis    AddCommandBufferBindingBuffer(dev_data, cb_state, buffer_state);
5698d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis}
5699d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis
5700bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count,
5701bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                           uint32_t stride) {
570256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
5703d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis    GLOBAL_CB_NODE *cb_state = nullptr;
5704d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis    BUFFER_STATE *buffer_state = nullptr;
5705ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
5706872a2f0ca3ffdeddfa7483e777191fa64b853892Tony Barbour    bool skip = PreCallValidateCmdDrawIndirect(dev_data, commandBuffer, buffer, false, VK_PIPELINE_BIND_POINT_GRAPHICS, &cb_state,
5707ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis                                               &buffer_state, "vkCmdDrawIndirect()");
5708b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
5709d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis    if (!skip) {
57104a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdDrawIndirect(commandBuffer, buffer, offset, count, stride);
5711d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis        lock.lock();
5712ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis        PostCallRecordCmdDrawIndirect(dev_data, cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, buffer_state);
5713d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis        lock.unlock();
5714d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis    }
57155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
57165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5717ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool PreCallValidateCmdDrawIndexedIndirect(layer_data *dev_data, VkCommandBuffer cmd_buffer, VkBuffer buffer, bool indexed,
5718ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis                                                  VkPipelineBindPoint bind_point, GLOBAL_CB_NODE **cb_state,
5719ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis                                                  BUFFER_STATE **buffer_state, const char *caller) {
5720315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis    bool skip =
5721315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        ValidateCmdDrawType(dev_data, cmd_buffer, indexed, bind_point, CMD_DRAWINDEXEDINDIRECT, cb_state, caller,
5722315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_1a602415, VALIDATION_ERROR_1a600017, VALIDATION_ERROR_1a600434);
57239a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    *buffer_state = GetBufferState(dev_data, buffer);
5724315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis    skip |= ValidateMemoryIsBoundToBuffer(dev_data, *buffer_state, caller, VALIDATION_ERROR_1a60041c);
572513c4316d0072cbc5bf3cd729abef4d114f3c96edMark Lobodzinski    // TODO: If the drawIndirectFirstInstance feature is not enabled, all the firstInstance members of the
572613c4316d0072cbc5bf3cd729abef4d114f3c96edMark Lobodzinski    // VkDrawIndexedIndirectCommand structures accessed by this command must be 0, which will require access to the contents of
572713c4316d0072cbc5bf3cd729abef4d114f3c96edMark Lobodzinski    // 'buffer'.
57280c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis    return skip;
57290c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis}
57300c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis
5731ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void PostCallRecordCmdDrawIndexedIndirect(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point,
5732ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis                                                 BUFFER_STATE *buffer_state) {
57336b33c4e6a6f232fca84e0a6229106717b0012488Chris Forbes    UpdateStateCmdDrawType(dev_data, cb_state, bind_point);
57340c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis    AddCommandBufferBindingBuffer(dev_data, cb_state, buffer_state);
57350c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis}
57360c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis
5737bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
5738bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                  uint32_t count, uint32_t stride) {
573956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
57400c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis    GLOBAL_CB_NODE *cb_state = nullptr;
57410c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis    BUFFER_STATE *buffer_state = nullptr;
5742ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
57430c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis    bool skip = PreCallValidateCmdDrawIndexedIndirect(dev_data, commandBuffer, buffer, true, VK_PIPELINE_BIND_POINT_GRAPHICS,
5744ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis                                                      &cb_state, &buffer_state, "vkCmdDrawIndexedIndirect()");
5745b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
57460c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis    if (!skip) {
57474a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdDrawIndexedIndirect(commandBuffer, buffer, offset, count, stride);
57480c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis        lock.lock();
5749ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis        PostCallRecordCmdDrawIndexedIndirect(dev_data, cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, buffer_state);
57500c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis        lock.unlock();
57510c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis    }
57525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
57535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5754ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool PreCallValidateCmdDispatch(layer_data *dev_data, VkCommandBuffer cmd_buffer, bool indexed,
5755ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis                                       VkPipelineBindPoint bind_point, GLOBAL_CB_NODE **cb_state, const char *caller) {
5756baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt    return ValidateCmdDrawType(dev_data, cmd_buffer, indexed, bind_point, CMD_DISPATCH, cb_state, caller, VK_QUEUE_COMPUTE_BIT,
5757315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                               VALIDATION_ERROR_19c02415, VALIDATION_ERROR_19c00017, VALIDATION_ERROR_UNDEFINED);
575825d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis}
575925d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis
5760ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void PostCallRecordCmdDispatch(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point) {
57616b33c4e6a6f232fca84e0a6229106717b0012488Chris Forbes    UpdateStateCmdDrawDispatchType(dev_data, cb_state, bind_point);
576225d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis}
576325d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis
576489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z) {
576556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
576625d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis    GLOBAL_CB_NODE *cb_state = nullptr;
5767ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
5768ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis    bool skip =
5769ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis        PreCallValidateCmdDispatch(dev_data, commandBuffer, false, VK_PIPELINE_BIND_POINT_COMPUTE, &cb_state, "vkCmdDispatch()");
5770b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
577125d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis    if (!skip) {
57724a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdDispatch(commandBuffer, x, y, z);
577325d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis        lock.lock();
5774ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis        PostCallRecordCmdDispatch(dev_data, cb_state, VK_PIPELINE_BIND_POINT_COMPUTE);
577525d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis        lock.unlock();
577625d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis    }
57775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
57785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5779ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool PreCallValidateCmdDispatchIndirect(layer_data *dev_data, VkCommandBuffer cmd_buffer, VkBuffer buffer, bool indexed,
5780ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis                                               VkPipelineBindPoint bind_point, GLOBAL_CB_NODE **cb_state,
5781ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis                                               BUFFER_STATE **buffer_state, const char *caller) {
5782baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt    bool skip =
5783baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt        ValidateCmdDrawType(dev_data, cmd_buffer, indexed, bind_point, CMD_DISPATCHINDIRECT, cb_state, caller, VK_QUEUE_COMPUTE_BIT,
5784315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            VALIDATION_ERROR_1a002415, VALIDATION_ERROR_1a000017, VALIDATION_ERROR_UNDEFINED);
57859a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    *buffer_state = GetBufferState(dev_data, buffer);
5786315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis    skip |= ValidateMemoryIsBoundToBuffer(dev_data, *buffer_state, caller, VALIDATION_ERROR_1a000322);
578779c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis    return skip;
578879c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis}
578979c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis
5790ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void PostCallRecordCmdDispatchIndirect(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point,
5791ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis                                              BUFFER_STATE *buffer_state) {
57926b33c4e6a6f232fca84e0a6229106717b0012488Chris Forbes    UpdateStateCmdDrawDispatchType(dev_data, cb_state, bind_point);
579379c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis    AddCommandBufferBindingBuffer(dev_data, cb_state, buffer_state);
579479c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis}
579579c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis
5796bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset) {
579756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
579879c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis    GLOBAL_CB_NODE *cb_state = nullptr;
579979c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis    BUFFER_STATE *buffer_state = nullptr;
5800ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
58017433ab60c7ff16d37edb0f8b17b606ccd363e210Tobin Ehlis    bool skip = PreCallValidateCmdDispatchIndirect(dev_data, commandBuffer, buffer, false, VK_PIPELINE_BIND_POINT_COMPUTE,
5802ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis                                                   &cb_state, &buffer_state, "vkCmdDispatchIndirect()");
5803b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
580479c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis    if (!skip) {
58054a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdDispatchIndirect(commandBuffer, buffer, offset);
580679c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis        lock.lock();
5807ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis        PostCallRecordCmdDispatchIndirect(dev_data, cb_state, VK_PIPELINE_BIND_POINT_COMPUTE, buffer_state);
580879c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis        lock.unlock();
580979c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis    }
58105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
58115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
581289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdCopyBuffer(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer,
581389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                         uint32_t regionCount, const VkBufferCopy *pRegions) {
5814c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
5815ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
5816ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis
5817c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    auto cb_node = GetCBNode(device_data, commandBuffer);
5818c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    auto src_buffer_state = GetBufferState(device_data, srcBuffer);
5819c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    auto dst_buffer_state = GetBufferState(device_data, dstBuffer);
5820593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis
5821c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    if (cb_node && src_buffer_state && dst_buffer_state) {
5822c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski        bool skip = PreCallValidateCmdCopyBuffer(device_data, cb_node, src_buffer_state, dst_buffer_state);
5823c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski        if (!skip) {
5824c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski            PreCallRecordCmdCopyBuffer(device_data, cb_node, src_buffer_state, dst_buffer_state);
5825c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski            lock.unlock();
5826c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski            device_data->dispatch_table.CmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, regionCount, pRegions);
5827c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski        }
5828ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    } else {
5829c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski        lock.unlock();
5830ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        assert(0);
58315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
58325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
58335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5834bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdCopyImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout,
5835bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                        VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount,
5836bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                        const VkImageCopy *pRegions) {
58376a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    bool skip = false;
58386a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
5839ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
5840249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis
58416a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    auto cb_node = GetCBNode(device_data, commandBuffer);
58426a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    auto src_image_state = GetImageState(device_data, srcImage);
58436a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    auto dst_image_state = GetImageState(device_data, dstImage);
58441facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis    if (cb_node && src_image_state && dst_image_state) {
58456a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        skip = PreCallValidateCmdCopyImage(device_data, cb_node, src_image_state, dst_image_state, regionCount, pRegions,
58466a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                           srcImageLayout, dstImageLayout);
58476a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if (!skip) {
5848a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis            PreCallRecordCmdCopyImage(device_data, cb_node, src_image_state, dst_image_state, regionCount, pRegions, srcImageLayout,
5849a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis                                      dstImageLayout);
58506a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            lock.unlock();
58516a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            device_data->dispatch_table.CmdCopyImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount,
58526a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                                     pRegions);
58535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
5854249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis    } else {
58556a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        lock.unlock();
5856249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis        assert(0);
58575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
58585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
58595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5860eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski// Validate that an image's sampleCount matches the requirement for a specific API call
586160568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinskibool ValidateImageSampleCount(layer_data *dev_data, IMAGE_STATE *image_state, VkSampleCountFlagBits sample_count,
586260568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski                              const char *location, UNIQUE_VALIDATION_ERROR_CODE msgCode) {
5863eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski    bool skip = false;
58641facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis    if (image_state->createInfo.samples != sample_count) {
58659b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus        skip = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
58669b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                       HandleToUint64(image_state->image), 0, msgCode, "DS",
58679b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                       "%s for image 0x%" PRIxLEAST64 " was created with a sample count of %s but must be %s. %s", location,
58689b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                       HandleToUint64(image_state->image), string_VkSampleCountFlagBits(image_state->createInfo.samples),
58699b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                       string_VkSampleCountFlagBits(sample_count), validation_error_map[msgCode]);
5870eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski    }
5871eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski    return skip;
5872eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski}
5873eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski
5874bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBlitImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout,
5875bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                        VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount,
5876bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                        const VkImageBlit *pRegions, VkFilter filter) {
587756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
5878ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
5879593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis
58809a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto cb_node = GetCBNode(dev_data, commandBuffer);
58819a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto src_image_state = GetImageState(dev_data, srcImage);
58829a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto dst_image_state = GetImageState(dev_data, dstImage);
58830dc51740dbd7b9f0ba7c071e0bf96f63d6d48c85Mark Lobodzinski
5884055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski    bool skip = PreCallValidateCmdBlitImage(dev_data, cb_node, src_image_state, dst_image_state, regionCount, pRegions, filter);
58850dc51740dbd7b9f0ba7c071e0bf96f63d6d48c85Mark Lobodzinski
5886dca02371c9531e7a9a2a51decae1db4d297862c4Mark Lobodzinski    if (!skip) {
5887eebd811afd800663f15fda8fc71bc203a03fe294Mark Lobodzinski        PreCallRecordCmdBlitImage(dev_data, cb_node, src_image_state, dst_image_state);
5888eebd811afd800663f15fda8fc71bc203a03fe294Mark Lobodzinski        lock.unlock();
58894a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdBlitImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount,
58904a0754042cf090e131e9e769d8a3633c228625beChris Forbes                                              pRegions, filter);
58910dc51740dbd7b9f0ba7c071e0bf96f63d6d48c85Mark Lobodzinski    }
58925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
58935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5894bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdCopyBufferToImage(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage,
5895bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                VkImageLayout dstImageLayout, uint32_t regionCount,
5896bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                const VkBufferImageCopy *pRegions) {
5897940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
5898ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
5899940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    bool skip = false;
5900940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    auto cb_node = GetCBNode(device_data, commandBuffer);
5901940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    auto src_buffer_state = GetBufferState(device_data, srcBuffer);
5902940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    auto dst_image_state = GetImageState(device_data, dstImage);
5903940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    if (cb_node && src_buffer_state && dst_image_state) {
5904940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski        skip = PreCallValidateCmdCopyBufferToImage(device_data, dstImageLayout, cb_node, src_buffer_state, dst_image_state,
590571c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                                                        regionCount, pRegions, "vkCmdCopyBufferToImage()");
5906ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    } else {
5907d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski        lock.unlock();
5908ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        assert(0);
5909e4d82c37d6c861b388dbc80297c18d6255858cb4Dave Houlton        // TODO: report VU01244 here, or put in object tracker?
59105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
5911940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    if (!skip) {
5912a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis        PreCallRecordCmdCopyBufferToImage(device_data, cb_node, src_buffer_state, dst_image_state, regionCount, pRegions,
5913a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis                                          dstImageLayout);
5914d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski        lock.unlock();
5915940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski        device_data->dispatch_table.CmdCopyBufferToImage(commandBuffer, srcBuffer, dstImage, dstImageLayout, regionCount, pRegions);
5916d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski    }
59175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
59185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5919bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdCopyImageToBuffer(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout,
5920bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                VkBuffer dstBuffer, uint32_t regionCount, const VkBufferImageCopy *pRegions) {
5921940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    bool skip = false;
5922940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
5923ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
5924593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis
5925940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    auto cb_node = GetCBNode(device_data, commandBuffer);
5926940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    auto src_image_state = GetImageState(device_data, srcImage);
5927940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    auto dst_buffer_state = GetBufferState(device_data, dstBuffer);
5928940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    if (cb_node && src_image_state && dst_buffer_state) {
5929940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski        skip = PreCallValidateCmdCopyImageToBuffer(device_data, srcImageLayout, cb_node, src_image_state, dst_buffer_state,
593071c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                                                        regionCount, pRegions, "vkCmdCopyImageToBuffer()");
5931ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    } else {
5932d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski        lock.unlock();
5933ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        assert(0);
5934e4d82c37d6c861b388dbc80297c18d6255858cb4Dave Houlton        // TODO: report VU01262 here, or put in object tracker?
59355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
5936940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    if (!skip) {
5937a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis        PreCallRecordCmdCopyImageToBuffer(device_data, cb_node, src_image_state, dst_buffer_state, regionCount, pRegions,
5938a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis                                          srcImageLayout);
5939d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski        lock.unlock();
5940940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski        device_data->dispatch_table.CmdCopyImageToBuffer(commandBuffer, srcImage, srcImageLayout, dstBuffer, regionCount, pRegions);
5941d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski    }
59425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
59435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5944e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlisstatic bool PreCallCmdUpdateBuffer(layer_data *device_data, const GLOBAL_CB_NODE *cb_state, const BUFFER_STATE *dst_buffer_state) {
5945e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis    bool skip = false;
5946e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis    skip |= ValidateMemoryIsBoundToBuffer(device_data, dst_buffer_state, "vkCmdUpdateBuffer()", VALIDATION_ERROR_1e400046);
5947e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis    // Validate that DST buffer has correct usage flags set
5948e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis    skip |= ValidateBufferUsageFlags(device_data, dst_buffer_state, VK_BUFFER_USAGE_TRANSFER_DST_BIT, true,
5949e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis                                     VALIDATION_ERROR_1e400044, "vkCmdUpdateBuffer()", "VK_BUFFER_USAGE_TRANSFER_DST_BIT");
5950e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis    skip |= ValidateCmdQueueFlags(device_data, cb_state, "vkCmdUpdateBuffer()",
5951e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis                                  VK_QUEUE_TRANSFER_BIT | VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, VALIDATION_ERROR_1e402415);
5952e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis    skip |= ValidateCmd(device_data, cb_state, CMD_UPDATEBUFFER, "vkCmdUpdateBuffer()");
5953e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis    skip |= insideRenderPass(device_data, cb_state, "vkCmdUpdateBuffer()", VALIDATION_ERROR_1e400017);
5954e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis    return skip;
5955e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis}
5956e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis
5957e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlisstatic void PostCallRecordCmdUpdateBuffer(layer_data *device_data, GLOBAL_CB_NODE *cb_state, BUFFER_STATE *dst_buffer_state) {
5958e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis    // Update bindings between buffer and cmd buffer
5959e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis    AddCommandBufferBindingBuffer(device_data, cb_state, dst_buffer_state);
5960e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis    std::function<bool()> function = [=]() {
5961e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis        SetBufferMemoryValid(device_data, dst_buffer_state, true);
5962e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis        return false;
5963e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis    };
5964e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis    cb_state->validate_functions.push_back(function);
5965e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis}
5966e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis
5967bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdUpdateBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset,
5968bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                           VkDeviceSize dataSize, const uint32_t *pData) {
59693251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
597056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
5971ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
5972593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis
5973e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis    auto cb_state = GetCBNode(dev_data, commandBuffer);
5974e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis    assert(cb_state);
59759a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto dst_buff_state = GetBufferState(dev_data, dstBuffer);
5976e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis    assert(dst_buff_state);
5977e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis    skip |= PreCallCmdUpdateBuffer(dev_data, cb_state, dst_buff_state);
5978b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
5979e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis    if (!skip) {
5980e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis        dev_data->dispatch_table.CmdUpdateBuffer(commandBuffer, dstBuffer, dstOffset, dataSize, pData);
5981e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis        lock.lock();
5982e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis        PostCallRecordCmdUpdateBuffer(dev_data, cb_state, dst_buff_state);
5983e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis        lock.unlock();
5984e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis    }
59855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
59865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5987bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdFillBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset,
5988bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                         VkDeviceSize size, uint32_t data) {
598923bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
5990ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
599123bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    auto cb_node = GetCBNode(device_data, commandBuffer);
599223bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    auto buffer_state = GetBufferState(device_data, dstBuffer);
5993593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis
599423bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    if (cb_node && buffer_state) {
599523bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski        bool skip = PreCallValidateCmdFillBuffer(device_data, cb_node, buffer_state);
599623bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski        if (!skip) {
599723bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski            PreCallRecordCmdFillBuffer(device_data, cb_node, buffer_state);
599823bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski            lock.unlock();
599923bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski            device_data->dispatch_table.CmdFillBuffer(commandBuffer, dstBuffer, dstOffset, size, data);
600023bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski        }
6001ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    } else {
600223bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski        lock.unlock();
6003ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        assert(0);
60045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
60055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
60065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
60074028af23e688ab5730f48ab2244dd042e2eefaedMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdClearAttachments(VkCommandBuffer commandBuffer, uint32_t attachmentCount,
60084028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski                                               const VkClearAttachment *pAttachments, uint32_t rectCount,
60094028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski                                               const VkClearRect *pRects) {
60104028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski    bool skip = false;
601156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
60124028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski    {
6013ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes        lock_guard_t lock(global_lock);
60144028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski        skip = PreCallValidateCmdClearAttachments(dev_data, commandBuffer, attachmentCount, pAttachments, rectCount, pRects);
60154028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski    }
6016cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (!skip) dev_data->dispatch_table.CmdClearAttachments(commandBuffer, attachmentCount, pAttachments, rectCount, pRects);
60175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
60185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
60190482c55760707900fcd072f6895c121bcf055f6eMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdClearColorImage(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout,
60200482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski                                              const VkClearColorValue *pColor, uint32_t rangeCount,
60210482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski                                              const VkImageSubresourceRange *pRanges) {
602256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
6023ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
60240482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski
60250482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski    bool skip = PreCallValidateCmdClearColorImage(dev_data, commandBuffer, image, imageLayout, rangeCount, pRanges);
60260482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski    if (!skip) {
60270619dc1df076bfedcf0c999ceca3bdecd5ea5171Chris Forbes        PreCallRecordCmdClearImage(dev_data, commandBuffer, image, imageLayout, rangeCount, pRanges);
60280482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski        lock.unlock();
60290482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski        dev_data->dispatch_table.CmdClearColorImage(commandBuffer, image, imageLayout, pColor, rangeCount, pRanges);
60300482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski    }
60310482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski}
60320482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski
60330482c55760707900fcd072f6895c121bcf055f6eMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdClearDepthStencilImage(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout,
60340482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski                                                     const VkClearDepthStencilValue *pDepthStencil, uint32_t rangeCount,
60350482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski                                                     const VkImageSubresourceRange *pRanges) {
603656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
6037ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
60380482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski
60390482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski    bool skip = PreCallValidateCmdClearDepthStencilImage(dev_data, commandBuffer, image, imageLayout, rangeCount, pRanges);
60400482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski    if (!skip) {
60410619dc1df076bfedcf0c999ceca3bdecd5ea5171Chris Forbes        PreCallRecordCmdClearImage(dev_data, commandBuffer, image, imageLayout, rangeCount, pRanges);
60420482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski        lock.unlock();
60430482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski        dev_data->dispatch_table.CmdClearDepthStencilImage(commandBuffer, image, imageLayout, pDepthStencil, rangeCount, pRanges);
60447f8aa8f5abceedbb599ef69af1dfbb38c0df2660Slawomir Cygan    }
60455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
60465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
6047bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdResolveImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout,
6048bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                           VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount,
6049bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                           const VkImageResolve *pRegions) {
605056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
6051ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
6052593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis
60539a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto cb_node = GetCBNode(dev_data, commandBuffer);
60549a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto src_image_state = GetImageState(dev_data, srcImage);
60559a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto dst_image_state = GetImageState(dev_data, dstImage);
605609fe5ac5edaec7f0dbcc9fd696e68194569aea89Mark Lobodzinski
605725f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski    bool skip = PreCallValidateCmdResolveImage(dev_data, cb_node, src_image_state, dst_image_state, regionCount, pRegions);
605809fe5ac5edaec7f0dbcc9fd696e68194569aea89Mark Lobodzinski
605909fe5ac5edaec7f0dbcc9fd696e68194569aea89Mark Lobodzinski    if (!skip) {
60606c0400e625554ce7fddb833eeace0de19cfcc965Mark Lobodzinski        PreCallRecordCmdResolveImage(dev_data, cb_node, src_image_state, dst_image_state);
60616c0400e625554ce7fddb833eeace0de19cfcc965Mark Lobodzinski        lock.unlock();
60624a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdResolveImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount,
60634a0754042cf090e131e9e769d8a3633c228625beChris Forbes                                                 pRegions);
606409fe5ac5edaec7f0dbcc9fd696e68194569aea89Mark Lobodzinski    }
60655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
60665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
6067a8d1e377bdeaf61a3209cb997502da4356a185bbMike WeiblenVKAPI_ATTR void VKAPI_CALL GetImageSubresourceLayout(VkDevice device, VkImage image, const VkImageSubresource *pSubresource,
6068a8d1e377bdeaf61a3209cb997502da4356a185bbMike Weiblen                                                     VkSubresourceLayout *pLayout) {
6069a8d1e377bdeaf61a3209cb997502da4356a185bbMike Weiblen    layer_data *device_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
6070a8d1e377bdeaf61a3209cb997502da4356a185bbMike Weiblen
6071a8d1e377bdeaf61a3209cb997502da4356a185bbMike Weiblen    bool skip = PreCallValidateGetImageSubresourceLayout(device_data, image, pSubresource);
6072a8d1e377bdeaf61a3209cb997502da4356a185bbMike Weiblen    if (!skip) {
6073b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski        device_data->dispatch_table.GetImageSubresourceLayout(device, image, pSubresource, pLayout);
6074b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski    }
6075b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski}
6076b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski
6077b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentinebool setEventStageMask(VkQueue queue, VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) {
607856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
60799a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer);
6080b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine    if (pCB) {
6081b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine        pCB->eventToStageMap[event] = stageMask;
6082b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine    }
6083b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine    auto queue_data = dev_data->queueMap.find(queue);
6084b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine    if (queue_data != dev_data->queueMap.end()) {
6085b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine        queue_data->second.eventToStageMap[event] = stageMask;
6086b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine    }
6087b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine    return false;
6088b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine}
6089b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine
6090bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) {
60913251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
609256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
6093ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
60949a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer);
60955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
60963251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetEvent()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT,
6097315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                      VALIDATION_ERROR_1d402415);
60983251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateCmd(dev_data, pCB, CMD_SETEVENT, "vkCmdSetEvent()");
6099315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= insideRenderPass(dev_data, pCB, "vkCmdSetEvent()", VALIDATION_ERROR_1d400017);
6100315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= ValidateStageMaskGsTsEnables(dev_data, stageMask, "vkCmdSetEvent()", VALIDATION_ERROR_1d4008fc,
6101315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                             VALIDATION_ERROR_1d4008fe);
61029a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto event_state = GetEventNode(dev_data, event);
61034710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis        if (event_state) {
61049b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus            addCommandBufferBinding(&event_state->cb_bindings, {HandleToUint64(event), kVulkanObjectTypeEvent}, pCB);
61054710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis            event_state->cb_bindings.insert(pCB);
6106ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis        }
61075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->events.push_back(event);
6108c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine        if (!pCB->waitedEvents.count(event)) {
6109c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine            pCB->writeEventsBeforeWait.push_back(event);
6110c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine        }
6111f49bd2b5f4c968a3033b3e5099bbbcff51201575Chris Forbes        pCB->eventUpdates.emplace_back([=](VkQueue q){return setEventStageMask(q, commandBuffer, event, stageMask);});
61125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
6113b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
61143251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (!skip) dev_data->dispatch_table.CmdSetEvent(commandBuffer, event, stageMask);
61155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
61165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
6117bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdResetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) {
61183251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
611956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
6120ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
61219a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer);
61225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
61233251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdResetEvent()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT,
6124315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                      VALIDATION_ERROR_1c402415);
61253251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateCmd(dev_data, pCB, CMD_RESETEVENT, "vkCmdResetEvent()");
6126315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= insideRenderPass(dev_data, pCB, "vkCmdResetEvent()", VALIDATION_ERROR_1c400017);
6127315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= ValidateStageMaskGsTsEnables(dev_data, stageMask, "vkCmdResetEvent()", VALIDATION_ERROR_1c400904,
6128315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                             VALIDATION_ERROR_1c400906);
61299a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto event_state = GetEventNode(dev_data, event);
61304710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis        if (event_state) {
61319b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus            addCommandBufferBinding(&event_state->cb_bindings, {HandleToUint64(event), kVulkanObjectTypeEvent}, pCB);
61324710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis            event_state->cb_bindings.insert(pCB);
6133ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis        }
61345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->events.push_back(event);
6135c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine        if (!pCB->waitedEvents.count(event)) {
6136c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine            pCB->writeEventsBeforeWait.push_back(event);
6137c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine        }
6138315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        // TODO : Add check for VALIDATION_ERROR_32c008f8
6139f49bd2b5f4c968a3033b3e5099bbbcff51201575Chris Forbes        pCB->eventUpdates.emplace_back([=](VkQueue q){return setEventStageMask(q, commandBuffer, event, VkPipelineStageFlags(0));});
61405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
6141b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
61423251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (!skip) dev_data->dispatch_table.CmdResetEvent(commandBuffer, event, stageMask);
61435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
61445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
6145a54aea2a72be3bd84371773cc79a678816615587Tobin Ehlis// Return input pipeline stage flags, expanded for individual bits if VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT
6146a54aea2a72be3bd84371773cc79a678816615587Tobin Ehlisstatic VkPipelineStageFlags ExpandPipelineStageFlags(VkPipelineStageFlags inflags) {
6147a54aea2a72be3bd84371773cc79a678816615587Tobin Ehlis    return (inflags != VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT)
6148a54aea2a72be3bd84371773cc79a678816615587Tobin Ehlis               ? inflags
6149a54aea2a72be3bd84371773cc79a678816615587Tobin Ehlis               : (VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT | VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT | VK_PIPELINE_STAGE_VERTEX_INPUT_BIT |
6150a54aea2a72be3bd84371773cc79a678816615587Tobin Ehlis                  VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT |
6151a54aea2a72be3bd84371773cc79a678816615587Tobin Ehlis                  VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT |
6152a54aea2a72be3bd84371773cc79a678816615587Tobin Ehlis                  VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
6153a54aea2a72be3bd84371773cc79a678816615587Tobin Ehlis                  VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
6154a54aea2a72be3bd84371773cc79a678816615587Tobin Ehlis                  VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT);
6155a54aea2a72be3bd84371773cc79a678816615587Tobin Ehlis}
6156a54aea2a72be3bd84371773cc79a678816615587Tobin Ehlis
6157f384f33742c2b72888372332747298d08135ac92Tobin Ehlis// Verify image barrier image state and that the image is consistent with FB image
6158f384f33742c2b72888372332747298d08135ac92Tobin Ehlisstatic bool ValidateImageBarrierImage(layer_data *device_data, const char *funcName, GLOBAL_CB_NODE const *cb_state,
615979fc00370d55e7cbfd4052b579120e64b0a1a4beTobin Ehlis                                      VkFramebuffer framebuffer, uint32_t active_subpass, const safe_VkSubpassDescription &sub_desc,
616079fc00370d55e7cbfd4052b579120e64b0a1a4beTobin Ehlis                                      uint64_t rp_handle, uint32_t img_index, const VkImageMemoryBarrier &img_barrier) {
6161f384f33742c2b72888372332747298d08135ac92Tobin Ehlis    bool skip = false;
616279fc00370d55e7cbfd4052b579120e64b0a1a4beTobin Ehlis    const auto &fb_state = GetFramebufferState(device_data, framebuffer);
6163f384f33742c2b72888372332747298d08135ac92Tobin Ehlis    assert(fb_state);
6164f384f33742c2b72888372332747298d08135ac92Tobin Ehlis    const auto img_bar_image = img_barrier.image;
6165f384f33742c2b72888372332747298d08135ac92Tobin Ehlis    bool image_match = false;
6166f384f33742c2b72888372332747298d08135ac92Tobin Ehlis    bool sub_image_found = false;  // Do we find a corresponding subpass description
6167f384f33742c2b72888372332747298d08135ac92Tobin Ehlis    VkImageLayout sub_image_layout = VK_IMAGE_LAYOUT_UNDEFINED;
6168f384f33742c2b72888372332747298d08135ac92Tobin Ehlis    uint32_t attach_index = 0;
6169f384f33742c2b72888372332747298d08135ac92Tobin Ehlis    uint32_t index_count = 0;
6170f384f33742c2b72888372332747298d08135ac92Tobin Ehlis    // Verify that a framebuffer image matches barrier image
6171f384f33742c2b72888372332747298d08135ac92Tobin Ehlis    for (const auto &fb_attach : fb_state->attachments) {
6172f384f33742c2b72888372332747298d08135ac92Tobin Ehlis        if (img_bar_image == fb_attach.image) {
6173f384f33742c2b72888372332747298d08135ac92Tobin Ehlis            image_match = true;
6174f384f33742c2b72888372332747298d08135ac92Tobin Ehlis            attach_index = index_count;
6175f384f33742c2b72888372332747298d08135ac92Tobin Ehlis            break;
6176f384f33742c2b72888372332747298d08135ac92Tobin Ehlis        }
6177f384f33742c2b72888372332747298d08135ac92Tobin Ehlis        index_count++;
6178f384f33742c2b72888372332747298d08135ac92Tobin Ehlis    }
6179f384f33742c2b72888372332747298d08135ac92Tobin Ehlis    if (image_match) {  // Make sure subpass is referring to matching attachment
6180f384f33742c2b72888372332747298d08135ac92Tobin Ehlis        if (sub_desc.pDepthStencilAttachment && sub_desc.pDepthStencilAttachment->attachment == attach_index) {
6181f384f33742c2b72888372332747298d08135ac92Tobin Ehlis            sub_image_layout = sub_desc.pDepthStencilAttachment->layout;
6182f384f33742c2b72888372332747298d08135ac92Tobin Ehlis            sub_image_found = true;
6183f384f33742c2b72888372332747298d08135ac92Tobin Ehlis        } else {
6184f384f33742c2b72888372332747298d08135ac92Tobin Ehlis            for (uint32_t j = 0; j < sub_desc.colorAttachmentCount; ++j) {
6185f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                if (sub_desc.pColorAttachments && sub_desc.pColorAttachments[j].attachment == attach_index) {
6186f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                    sub_image_layout = sub_desc.pColorAttachments[j].layout;
6187f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                    sub_image_found = true;
6188f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                    break;
6189f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                } else if (sub_desc.pResolveAttachments && sub_desc.pResolveAttachments[j].attachment == attach_index) {
6190f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                    sub_image_layout = sub_desc.pResolveAttachments[j].layout;
6191f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                    sub_image_found = true;
6192f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                    break;
6193f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                }
6194f384f33742c2b72888372332747298d08135ac92Tobin Ehlis            }
6195f384f33742c2b72888372332747298d08135ac92Tobin Ehlis        }
6196f384f33742c2b72888372332747298d08135ac92Tobin Ehlis        if (!sub_image_found) {
6197f384f33742c2b72888372332747298d08135ac92Tobin Ehlis            skip |= log_msg(
6198f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT, rp_handle,
6199f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                __LINE__, VALIDATION_ERROR_1b800936, "CORE",
6200f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                "%s: Barrier pImageMemoryBarriers[%d].image (0x%" PRIx64
6201f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                ") is not referenced by the VkSubpassDescription for active subpass (%d) of current renderPass (0x%" PRIx64 "). %s",
6202f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                funcName, img_index, HandleToUint64(img_bar_image), active_subpass, rp_handle,
6203f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                validation_error_map[VALIDATION_ERROR_1b800936]);
6204f384f33742c2b72888372332747298d08135ac92Tobin Ehlis        }
6205f384f33742c2b72888372332747298d08135ac92Tobin Ehlis    } else {  // !image_match
6206f384f33742c2b72888372332747298d08135ac92Tobin Ehlis        auto const fb_handle = HandleToUint64(fb_state->framebuffer);
6207f384f33742c2b72888372332747298d08135ac92Tobin Ehlis        skip |=
6208f384f33742c2b72888372332747298d08135ac92Tobin Ehlis            log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT, fb_handle,
6209f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                    __LINE__, VALIDATION_ERROR_1b800936, "CORE",
6210f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                    "%s: Barrier pImageMemoryBarriers[%d].image (0x%" PRIx64
6211f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                    ") does not match an image from the current framebuffer (0x%" PRIx64 "). %s",
6212f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                    funcName, img_index, HandleToUint64(img_bar_image), fb_handle, validation_error_map[VALIDATION_ERROR_1b800936]);
6213f384f33742c2b72888372332747298d08135ac92Tobin Ehlis    }
6214f384f33742c2b72888372332747298d08135ac92Tobin Ehlis    if (img_barrier.oldLayout != img_barrier.newLayout) {
6215f384f33742c2b72888372332747298d08135ac92Tobin Ehlis        skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
6216f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                        HandleToUint64(cb_state->commandBuffer), __LINE__, VALIDATION_ERROR_1b80093a, "CORE",
6217f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                        "%s: As the Image Barrier for image 0x%" PRIx64
6218f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                        " is being executed within a render pass instance, oldLayout must equal newLayout yet they are "
6219f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                        "%s and %s. %s",
6220f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                        funcName, HandleToUint64(img_barrier.image), string_VkImageLayout(img_barrier.oldLayout),
6221f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                        string_VkImageLayout(img_barrier.newLayout), validation_error_map[VALIDATION_ERROR_1b80093a]);
6222f384f33742c2b72888372332747298d08135ac92Tobin Ehlis    } else {
6223f384f33742c2b72888372332747298d08135ac92Tobin Ehlis        if (sub_image_found && sub_image_layout != img_barrier.oldLayout) {
6224f384f33742c2b72888372332747298d08135ac92Tobin Ehlis            skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT,
6225f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                            rp_handle, __LINE__, VALIDATION_ERROR_1b800938, "CORE",
6226f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                            "%s: Barrier pImageMemoryBarriers[%d].image (0x%" PRIx64
6227f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                            ") is referenced by the VkSubpassDescription for active subpass (%d) of current renderPass (0x%" PRIx64
6228f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                            ") as having layout %s, but image barrier has layout %s. %s",
6229f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                            funcName, img_index, HandleToUint64(img_bar_image), active_subpass, rp_handle,
6230f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                            string_VkImageLayout(img_barrier.oldLayout), string_VkImageLayout(sub_image_layout),
6231f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                            validation_error_map[VALIDATION_ERROR_1b800938]);
6232f384f33742c2b72888372332747298d08135ac92Tobin Ehlis        }
6233f384f33742c2b72888372332747298d08135ac92Tobin Ehlis    }
6234f384f33742c2b72888372332747298d08135ac92Tobin Ehlis    return skip;
6235f384f33742c2b72888372332747298d08135ac92Tobin Ehlis}
6236f384f33742c2b72888372332747298d08135ac92Tobin Ehlis
62374cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis// Validate image barriers within a renderPass
6238f384f33742c2b72888372332747298d08135ac92Tobin Ehlisstatic bool ValidateRenderPassImageBarriers(layer_data *device_data, const char *funcName, GLOBAL_CB_NODE *cb_state,
62394cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                                            uint32_t active_subpass, const safe_VkSubpassDescription &sub_desc, uint64_t rp_handle,
62404cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                                            VkAccessFlags sub_src_access_mask, VkAccessFlags sub_dst_access_mask,
62414cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                                            uint32_t image_mem_barrier_count, const VkImageMemoryBarrier *image_barriers) {
6242a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis    bool skip = false;
62434cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis    for (uint32_t i = 0; i < image_mem_barrier_count; ++i) {
62444cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        const auto &img_barrier = image_barriers[i];
62454cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        const auto &img_src_access_mask = img_barrier.srcAccessMask;
62464cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        if (img_src_access_mask != (sub_src_access_mask & img_src_access_mask)) {
6247c1c43cc01e333f3762c65ce4ad926c33235583d2Tobin Ehlis            skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT,
62484cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            rp_handle, __LINE__, VALIDATION_ERROR_1b80092e, "CORE",
62494cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            "%s: Barrier pImageMemoryBarriers[%d].srcAccessMask(0x%X) is not a subset of VkSubpassDependency "
62504cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            "srcAccessMask(0x%X) of "
6251e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                            "subpass %d of renderPass 0x%" PRIx64 ". %s",
62524cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            funcName, i, img_src_access_mask, sub_src_access_mask, active_subpass, rp_handle,
62534cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            validation_error_map[VALIDATION_ERROR_1b80092e]);
6254e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis        }
62554cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        const auto &img_dst_access_mask = img_barrier.dstAccessMask;
62564cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        if (img_dst_access_mask != (sub_dst_access_mask & img_dst_access_mask)) {
6257c1c43cc01e333f3762c65ce4ad926c33235583d2Tobin Ehlis            skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT,
62584cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            rp_handle, __LINE__, VALIDATION_ERROR_1b800930, "CORE",
62594cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            "%s: Barrier pImageMemoryBarriers[%d].dstAccessMask(0x%X) is not a subset of VkSubpassDependency "
62604cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            "dstAccessMask(0x%X) of "
6261e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                            "subpass %d of renderPass 0x%" PRIx64 ". %s",
62624cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            funcName, i, img_dst_access_mask, sub_dst_access_mask, active_subpass, rp_handle,
62634cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            validation_error_map[VALIDATION_ERROR_1b800930]);
62645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
62658f2467c1db3d48bcfd09dd91188dcb0318fa5c43Tobin Ehlis        if (VK_QUEUE_FAMILY_IGNORED != img_barrier.srcQueueFamilyIndex ||
62668f2467c1db3d48bcfd09dd91188dcb0318fa5c43Tobin Ehlis            VK_QUEUE_FAMILY_IGNORED != img_barrier.dstQueueFamilyIndex) {
62678f2467c1db3d48bcfd09dd91188dcb0318fa5c43Tobin Ehlis            skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT,
62688f2467c1db3d48bcfd09dd91188dcb0318fa5c43Tobin Ehlis                            rp_handle, __LINE__, VALIDATION_ERROR_1b80093c, "CORE",
62698f2467c1db3d48bcfd09dd91188dcb0318fa5c43Tobin Ehlis                            "%s: Barrier pImageMemoryBarriers[%d].srcQueueFamilyIndex is %d and "
62708f2467c1db3d48bcfd09dd91188dcb0318fa5c43Tobin Ehlis                            "pImageMemoryBarriers[%d].dstQueueFamilyIndex is %d but both must be VK_QUEUE_FAMILY_IGNORED. %s",
62718f2467c1db3d48bcfd09dd91188dcb0318fa5c43Tobin Ehlis                            funcName, i, img_barrier.srcQueueFamilyIndex, i, img_barrier.dstQueueFamilyIndex,
62728f2467c1db3d48bcfd09dd91188dcb0318fa5c43Tobin Ehlis                            validation_error_map[VALIDATION_ERROR_1b80093c]);
62738f2467c1db3d48bcfd09dd91188dcb0318fa5c43Tobin Ehlis        }
6274f384f33742c2b72888372332747298d08135ac92Tobin Ehlis        // Secondary CBs can have null framebuffer so queue up validation in that case 'til FB is known
6275f384f33742c2b72888372332747298d08135ac92Tobin Ehlis        if (VK_NULL_HANDLE == cb_state->activeFramebuffer) {
6276f384f33742c2b72888372332747298d08135ac92Tobin Ehlis            assert(VK_COMMAND_BUFFER_LEVEL_SECONDARY == cb_state->createInfo.level);
6277f384f33742c2b72888372332747298d08135ac92Tobin Ehlis            // Secondary CB case w/o FB specified delay validation
627879fc00370d55e7cbfd4052b579120e64b0a1a4beTobin Ehlis            cb_state->cmd_execute_commands_functions.emplace_back([=](VkFramebuffer fb) {
627979fc00370d55e7cbfd4052b579120e64b0a1a4beTobin Ehlis                return ValidateImageBarrierImage(device_data, funcName, cb_state, fb, active_subpass, sub_desc, rp_handle, i,
6280f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                                                 img_barrier);
6281f384f33742c2b72888372332747298d08135ac92Tobin Ehlis            });
6282f384f33742c2b72888372332747298d08135ac92Tobin Ehlis        } else {
628379fc00370d55e7cbfd4052b579120e64b0a1a4beTobin Ehlis            skip |= ValidateImageBarrierImage(device_data, funcName, cb_state, cb_state->activeFramebuffer, active_subpass,
628479fc00370d55e7cbfd4052b579120e64b0a1a4beTobin Ehlis                                              sub_desc, rp_handle, i, img_barrier);
62853025e72bc2b727622969d036966f50057392551aTobin Ehlis        }
62864cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis    }
62874cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis    return skip;
62884cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis}
62894cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis
62904cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis// Validate VUs for Pipeline Barriers that are within a renderPass
62914cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis// Pre: cb_state->activeRenderPass must be a pointer to valid renderPass state
6292f384f33742c2b72888372332747298d08135ac92Tobin Ehlisstatic bool ValidateRenderPassPipelineBarriers(layer_data *device_data, const char *funcName, GLOBAL_CB_NODE *cb_state,
62934cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                                               VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask,
62944cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                                               VkDependencyFlags dependency_flags, uint32_t mem_barrier_count,
62954cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                                               const VkMemoryBarrier *mem_barriers, uint32_t buffer_mem_barrier_count,
62964cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                                               const VkBufferMemoryBarrier *buffer_mem_barriers, uint32_t image_mem_barrier_count,
62974cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                                               const VkImageMemoryBarrier *image_barriers) {
62984cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis    bool skip = false;
62994cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis    auto rp_state = cb_state->activeRenderPass;
63004cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis    const auto active_subpass = cb_state->activeSubpass;
63014cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis    auto rp_handle = HandleToUint64(rp_state->renderPass);
63024cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis    if (!rp_state->hasSelfDependency[active_subpass]) {
63034cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT,
63044cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                        rp_handle, __LINE__, VALIDATION_ERROR_1b800928, "CORE",
63054cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                        "%s: Barriers cannot be set during subpass %d of renderPass 0x%" PRIx64
63064cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                        " with no self-dependency specified. %s",
63074cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                        funcName, active_subpass, rp_handle, validation_error_map[VALIDATION_ERROR_1b800928]);
63084cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis    } else {
63094cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        assert(rp_state->subpass_to_dependency_index[cb_state->activeSubpass] != -1);
63104cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        // Grab ref to current subpassDescription up-front for use below
63114cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        const auto &sub_desc = rp_state->createInfo.pSubpasses[active_subpass];
63124cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        const auto &sub_dep = rp_state->createInfo.pDependencies[rp_state->subpass_to_dependency_index[active_subpass]];
63134cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        const auto &sub_src_stage_mask = ExpandPipelineStageFlags(sub_dep.srcStageMask);
63144cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        const auto &sub_dst_stage_mask = ExpandPipelineStageFlags(sub_dep.dstStageMask);
63154cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        if ((sub_src_stage_mask != VK_PIPELINE_STAGE_ALL_COMMANDS_BIT) &&
63164cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis            (src_stage_mask != (sub_src_stage_mask & src_stage_mask))) {
63174cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis            skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT,
63184cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            rp_handle, __LINE__, VALIDATION_ERROR_1b80092a, "CORE",
63194cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            "%s: Barrier srcStageMask(0x%X) is not a subset of VkSubpassDependency srcStageMask(0x%X) of "
63204cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            "subpass %d of renderPass 0x%" PRIx64 ". %s",
63214cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            funcName, src_stage_mask, sub_src_stage_mask, active_subpass, rp_handle,
63224cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            validation_error_map[VALIDATION_ERROR_1b80092a]);
63234cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        }
63244cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        if ((sub_dst_stage_mask != VK_PIPELINE_STAGE_ALL_COMMANDS_BIT) &&
63254cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis            (dst_stage_mask != (sub_dst_stage_mask & dst_stage_mask))) {
63264cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis            skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT,
63274cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            rp_handle, __LINE__, VALIDATION_ERROR_1b80092c, "CORE",
63284cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            "%s: Barrier dstStageMask(0x%X) is not a subset of VkSubpassDependency dstStageMask(0x%X) of "
63294cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            "subpass %d of renderPass 0x%" PRIx64 ". %s",
63304cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            funcName, dst_stage_mask, sub_dst_stage_mask, active_subpass, rp_handle,
63314cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            validation_error_map[VALIDATION_ERROR_1b80092c]);
63324cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        }
63334cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        if (0 != buffer_mem_barrier_count) {
63344cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis            skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT,
63354cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            rp_handle, __LINE__, VALIDATION_ERROR_1b800934, "CORE",
63364cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            "%s: bufferMemoryBarrierCount is non-zero (%d) for "
63374cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            "subpass %d of renderPass 0x%" PRIx64 ". %s",
63384cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            funcName, buffer_mem_barrier_count, active_subpass, rp_handle,
63394cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            validation_error_map[VALIDATION_ERROR_1b800934]);
63404cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        }
63414cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        const auto &sub_src_access_mask = sub_dep.srcAccessMask;
63424cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        const auto &sub_dst_access_mask = sub_dep.dstAccessMask;
63434cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        for (uint32_t i = 0; i < mem_barrier_count; ++i) {
63444cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis            const auto &mb_src_access_mask = mem_barriers[i].srcAccessMask;
63454cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis            if (mb_src_access_mask != (sub_src_access_mask & mb_src_access_mask)) {
63464cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
63474cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                                VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT, rp_handle, __LINE__, VALIDATION_ERROR_1b80092e, "CORE",
63484cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                                "%s: Barrier pMemoryBarriers[%d].srcAccessMask(0x%X) is not a subset of VkSubpassDependency "
63494cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                                "srcAccessMask(0x%X) of "
63504cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                                "subpass %d of renderPass 0x%" PRIx64 ". %s",
63514cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                                funcName, i, mb_src_access_mask, sub_src_access_mask, active_subpass, rp_handle,
63524cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                                validation_error_map[VALIDATION_ERROR_1b80092e]);
63534cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis            }
63544cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis            const auto &mb_dst_access_mask = mem_barriers[i].dstAccessMask;
63554cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis            if (mb_dst_access_mask != (sub_dst_access_mask & mb_dst_access_mask)) {
63564cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
63574cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                                VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT, rp_handle, __LINE__, VALIDATION_ERROR_1b800930, "CORE",
63584cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                                "%s: Barrier pMemoryBarriers[%d].dstAccessMask(0x%X) is not a subset of VkSubpassDependency "
63594cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                                "dstAccessMask(0x%X) of "
63604cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                                "subpass %d of renderPass 0x%" PRIx64 ". %s",
63614cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                                funcName, i, mb_dst_access_mask, sub_dst_access_mask, active_subpass, rp_handle,
63624cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                                validation_error_map[VALIDATION_ERROR_1b800930]);
63634cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis            }
63644cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        }
63654cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        skip |= ValidateRenderPassImageBarriers(device_data, funcName, cb_state, active_subpass, sub_desc, rp_handle,
63664cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                                                sub_src_access_mask, sub_dst_access_mask, image_mem_barrier_count, image_barriers);
6367c1c43cc01e333f3762c65ce4ad926c33235583d2Tobin Ehlis        if (sub_dep.dependencyFlags != dependency_flags) {
6368c1c43cc01e333f3762c65ce4ad926c33235583d2Tobin Ehlis            skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT,
6369c1c43cc01e333f3762c65ce4ad926c33235583d2Tobin Ehlis                            rp_handle, __LINE__, VALIDATION_ERROR_1b800932, "CORE",
6370c1c43cc01e333f3762c65ce4ad926c33235583d2Tobin Ehlis                            "%s: dependencyFlags param (0x%X) does not equal VkSubpassDependency "
6371c1c43cc01e333f3762c65ce4ad926c33235583d2Tobin Ehlis                            "dependencyFlags value (0x%X) for "
6372c1c43cc01e333f3762c65ce4ad926c33235583d2Tobin Ehlis                            "subpass %d of renderPass 0x%" PRIx64 ". %s",
6373c1c43cc01e333f3762c65ce4ad926c33235583d2Tobin Ehlis                            funcName, dependency_flags, sub_dep.dependencyFlags, cb_state->activeSubpass, rp_handle,
6374c1c43cc01e333f3762c65ce4ad926c33235583d2Tobin Ehlis                            validation_error_map[VALIDATION_ERROR_1b800932]);
6375c1c43cc01e333f3762c65ce4ad926c33235583d2Tobin Ehlis        }
63765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
6377e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis    return skip;
6378e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis}
6379e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis
6380d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis// Array to mask individual accessMask to corresponding stageMask
6381d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis//  accessMask active bit position (0-31) maps to index
6382d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlisconst static VkPipelineStageFlags AccessMaskToPipeStage[20] = {
6383d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    // VK_ACCESS_INDIRECT_COMMAND_READ_BIT = 0
6384d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT,
6385d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    // VK_ACCESS_INDEX_READ_BIT = 1
6386d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    VK_PIPELINE_STAGE_VERTEX_INPUT_BIT,
6387d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    // VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT = 2
6388d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    VK_PIPELINE_STAGE_VERTEX_INPUT_BIT,
6389d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    // VK_ACCESS_UNIFORM_READ_BIT = 3
6390d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT |
6391d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis        VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT |
6392d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis        VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
6393d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    // VK_ACCESS_INPUT_ATTACHMENT_READ_BIT = 4
6394d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
6395d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    // VK_ACCESS_SHADER_READ_BIT = 5
6396d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT |
6397d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis        VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT |
6398d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis        VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
6399d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    // VK_ACCESS_SHADER_WRITE_BIT = 6
6400d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT |
6401d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis        VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT |
6402d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis        VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
6403d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    // VK_ACCESS_COLOR_ATTACHMENT_READ_BIT = 7
6404d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
6405d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    // VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT = 8
6406d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
6407d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    // VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT = 9
6408d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
6409d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    // VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT = 10
6410d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
6411d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    // VK_ACCESS_TRANSFER_READ_BIT = 11
6412d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    VK_PIPELINE_STAGE_TRANSFER_BIT,
6413d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    // VK_ACCESS_TRANSFER_WRITE_BIT = 12
6414d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    VK_PIPELINE_STAGE_TRANSFER_BIT,
6415d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    // VK_ACCESS_HOST_READ_BIT = 13
6416d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    VK_PIPELINE_STAGE_HOST_BIT,
6417d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    // VK_ACCESS_HOST_WRITE_BIT = 14
6418d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    VK_PIPELINE_STAGE_HOST_BIT,
6419d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    // VK_ACCESS_MEMORY_READ_BIT = 15
6420d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    VK_ACCESS_FLAG_BITS_MAX_ENUM,  // Always match
6421d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    // VK_ACCESS_MEMORY_WRITE_BIT = 16
6422d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    VK_ACCESS_FLAG_BITS_MAX_ENUM,  // Always match
6423d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    // VK_ACCESS_COMMAND_PROCESS_READ_BIT_NVX = 17
6424d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX,
6425d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    // VK_ACCESS_COMMAND_PROCESS_WRITE_BIT_NVX = 18
6426d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX,
6427d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis};
6428d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis
6429d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis// Verify that all bits of access_mask are supported by the src_stage_mask
6430d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlisstatic bool ValidateAccessMaskPipelineStage(VkAccessFlags access_mask, VkPipelineStageFlags stage_mask) {
6431d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    // Early out if all commands set, or access_mask NULL
6432d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    if ((stage_mask & VK_PIPELINE_STAGE_ALL_COMMANDS_BIT) || (0 == access_mask)) return true;
6433d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis
6434d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    stage_mask = ExpandPipelineStageFlags(stage_mask);
6435d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    int index = 0;
6436d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    // for each of the set bits in access_mask, make sure that supporting stage mask bit(s) are set
6437d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    while (access_mask) {
6438d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis        index = (u_ffs(access_mask) - 1);
6439d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis        assert(index >= 0);
6440d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis        // Must have "!= 0" compare to prevent warning from MSVC
6441d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis        if ((AccessMaskToPipeStage[index] & stage_mask) == 0) return false;  // early out
6442d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis        access_mask &= ~(1 << index);                                        // Mask off bit that's been checked
6443d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    }
6444d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    return true;
6445d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis}
6446d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis
6447e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlisstatic bool ValidateBarriers(layer_data *device_data, const char *funcName, GLOBAL_CB_NODE const *cb_state,
6448e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                             VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask, uint32_t memBarrierCount,
6449e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                             const VkMemoryBarrier *pMemBarriers, uint32_t bufferBarrierCount,
6450e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                             const VkBufferMemoryBarrier *pBufferMemBarriers, uint32_t imageMemBarrierCount,
6451e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                             const VkImageMemoryBarrier *pImageMemBarriers) {
6452e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis    bool skip = false;
6453d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    for (uint32_t i = 0; i < memBarrierCount; ++i) {
6454d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis        const auto &mem_barrier = pMemBarriers[i];
6455d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis        if (!ValidateAccessMaskPipelineStage(mem_barrier.srcAccessMask, src_stage_mask)) {
6456d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis            skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
6457d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis                            HandleToUint64(cb_state->commandBuffer), __LINE__, VALIDATION_ERROR_1b800940, "DS",
6458d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis                            "%s: pMemBarriers[%d].srcAccessMask (0x%X) is not supported by srcStageMask (0x%X). %s", funcName, i,
6459d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis                            mem_barrier.srcAccessMask, src_stage_mask, validation_error_map[VALIDATION_ERROR_1b800940]);
6460d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis        }
64611ce9b1e7d3dfd0841efede007022bdc960917008Tobin Ehlis        if (!ValidateAccessMaskPipelineStage(mem_barrier.dstAccessMask, dst_stage_mask)) {
64621ce9b1e7d3dfd0841efede007022bdc960917008Tobin Ehlis            skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
64631ce9b1e7d3dfd0841efede007022bdc960917008Tobin Ehlis                            HandleToUint64(cb_state->commandBuffer), __LINE__, VALIDATION_ERROR_1b800942, "DS",
64641ce9b1e7d3dfd0841efede007022bdc960917008Tobin Ehlis                            "%s: pMemBarriers[%d].dstAccessMask (0x%X) is not supported by dstStageMask (0x%X). %s", funcName, i,
64651ce9b1e7d3dfd0841efede007022bdc960917008Tobin Ehlis                            mem_barrier.dstAccessMask, dst_stage_mask, validation_error_map[VALIDATION_ERROR_1b800942]);
64661ce9b1e7d3dfd0841efede007022bdc960917008Tobin Ehlis        }
6467d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    }
64685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < imageMemBarrierCount; ++i) {
64695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        auto mem_barrier = &pImageMemBarriers[i];
6470d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis        if (!ValidateAccessMaskPipelineStage(mem_barrier->srcAccessMask, src_stage_mask)) {
6471d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis            skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
6472d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis                            HandleToUint64(cb_state->commandBuffer), __LINE__, VALIDATION_ERROR_1b800940, "DS",
6473d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis                            "%s: pImageMemBarriers[%d].srcAccessMask (0x%X) is not supported by srcStageMask (0x%X). %s", funcName,
6474d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis                            i, mem_barrier->srcAccessMask, src_stage_mask, validation_error_map[VALIDATION_ERROR_1b800940]);
6475d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis        }
64761ce9b1e7d3dfd0841efede007022bdc960917008Tobin Ehlis        if (!ValidateAccessMaskPipelineStage(mem_barrier->dstAccessMask, dst_stage_mask)) {
64771ce9b1e7d3dfd0841efede007022bdc960917008Tobin Ehlis            skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
64781ce9b1e7d3dfd0841efede007022bdc960917008Tobin Ehlis                            HandleToUint64(cb_state->commandBuffer), __LINE__, VALIDATION_ERROR_1b800942, "DS",
64791ce9b1e7d3dfd0841efede007022bdc960917008Tobin Ehlis                            "%s: pImageMemBarriers[%d].dstAccessMask (0x%X) is not supported by dstStageMask (0x%X). %s", funcName,
64801ce9b1e7d3dfd0841efede007022bdc960917008Tobin Ehlis                            i, mem_barrier->dstAccessMask, dst_stage_mask, validation_error_map[VALIDATION_ERROR_1b800942]);
64811ce9b1e7d3dfd0841efede007022bdc960917008Tobin Ehlis        }
6482e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis        auto image_data = GetImageState(device_data, mem_barrier->image);
64838f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski        if (image_data) {
64848f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski            uint32_t src_q_f_index = mem_barrier->srcQueueFamilyIndex;
64858f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski            uint32_t dst_q_f_index = mem_barrier->dstQueueFamilyIndex;
64868f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski            if (image_data->createInfo.sharingMode == VK_SHARING_MODE_CONCURRENT) {
64878f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski                // srcQueueFamilyIndex and dstQueueFamilyIndex must both
64888f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski                // be VK_QUEUE_FAMILY_IGNORED
64898f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski                if ((src_q_f_index != VK_QUEUE_FAMILY_IGNORED) || (dst_q_f_index != VK_QUEUE_FAMILY_IGNORED)) {
6490e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                    skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
6491e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                                    VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, HandleToUint64(cb_state->commandBuffer),
6492e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                                    __LINE__, DRAWSTATE_INVALID_QUEUE_INDEX, "DS",
6493e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                                    "%s: Image Barrier for image 0x%" PRIx64
6494e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                                    " was created with sharingMode of "
6495e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                                    "VK_SHARING_MODE_CONCURRENT. Src and dst "
6496e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                                    "queueFamilyIndices must be VK_QUEUE_FAMILY_IGNORED.",
64979b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                    funcName, HandleToUint64(mem_barrier->image));
64988f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski                }
64998f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski            } else {
65008f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski                // Sharing mode is VK_SHARING_MODE_EXCLUSIVE. srcQueueFamilyIndex and
65018f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski                // dstQueueFamilyIndex must either both be VK_QUEUE_FAMILY_IGNORED,
65028f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski                // or both be a valid queue family
65038f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski                if (((src_q_f_index == VK_QUEUE_FAMILY_IGNORED) || (dst_q_f_index == VK_QUEUE_FAMILY_IGNORED)) &&
65048f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski                    (src_q_f_index != dst_q_f_index)) {
6505e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                    skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
6506e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                                    VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, HandleToUint64(cb_state->commandBuffer),
6507e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                                    __LINE__, DRAWSTATE_INVALID_QUEUE_INDEX, "DS",
6508e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                                    "%s: Image 0x%" PRIx64
6509e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                                    " was created with sharingMode "
6510e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                                    "of VK_SHARING_MODE_EXCLUSIVE. If one of src- or "
6511e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                                    "dstQueueFamilyIndex is VK_QUEUE_FAMILY_IGNORED, both "
6512e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                                    "must be.",
65139b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                    funcName, HandleToUint64(mem_barrier->image));
65148f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski                } else if (((src_q_f_index != VK_QUEUE_FAMILY_IGNORED) && (dst_q_f_index != VK_QUEUE_FAMILY_IGNORED)) &&
6515e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                           ((src_q_f_index >= device_data->phys_dev_properties.queue_family_properties.size()) ||
6516e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                            (dst_q_f_index >= device_data->phys_dev_properties.queue_family_properties.size()))) {
6517e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                    skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
6518e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                                    VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, HandleToUint64(cb_state->commandBuffer),
6519e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                                    __LINE__, DRAWSTATE_INVALID_QUEUE_INDEX, "DS",
65208f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski                                    "%s: Image 0x%" PRIx64
65218f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski                                    " was created with sharingMode "
65228f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski                                    "of VK_SHARING_MODE_EXCLUSIVE, but srcQueueFamilyIndex %d"
65238f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski                                    " or dstQueueFamilyIndex %d is greater than " PRINTF_SIZE_T_SPECIFIER
65248f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski                                    "queueFamilies crated for this device.",
65259b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                    funcName, HandleToUint64(mem_barrier->image), src_q_f_index, dst_q_f_index,
6526e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                                    device_data->phys_dev_properties.queue_family_properties.size());
65275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
65285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
65298f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski        }
65305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
65318f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski        if (mem_barrier->oldLayout != mem_barrier->newLayout) {
6532e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis            skip |= ValidateMaskBitsFromLayouts(device_data, cb_state->commandBuffer, mem_barrier->srcAccessMask,
6533e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                                                mem_barrier->oldLayout, "Source");
6534e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis            skip |= ValidateMaskBitsFromLayouts(device_data, cb_state->commandBuffer, mem_barrier->dstAccessMask,
6535e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                                                mem_barrier->newLayout, "Dest");
65368f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski        }
65378f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski        if (mem_barrier->newLayout == VK_IMAGE_LAYOUT_UNDEFINED || mem_barrier->newLayout == VK_IMAGE_LAYOUT_PREINITIALIZED) {
6538e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis            skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
6539e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                            HandleToUint64(cb_state->commandBuffer), __LINE__, DRAWSTATE_INVALID_BARRIER, "DS",
6540df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                            "%s: Image Layout cannot be transitioned to UNDEFINED or "
6541df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                            "PREINITIALIZED.",
6542df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                            funcName);
65438f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski        }
65448f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski        if (image_data) {
65458f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski            auto aspect_mask = mem_barrier->subresourceRange.aspectMask;
6546e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis            skip |= ValidateImageAspectMask(device_data, image_data->image, image_data->createInfo.format, aspect_mask, funcName);
654795b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski
654823c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus            std::string param_name = "pImageMemoryBarriers[" + std::to_string(i) + "].subresourceRange";
6549e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis            skip |= ValidateImageSubresourceRange(device_data, image_data, false, mem_barrier->subresourceRange, funcName,
655023c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus                                                  param_name.c_str());
65515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
65525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
65532044b110851e8f1b75d6d406a0c88612476c63dbChris Forbes
65545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < bufferBarrierCount; ++i) {
65555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        auto mem_barrier = &pBufferMemBarriers[i];
6556cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        if (!mem_barrier) continue;
65575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
6558d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis        if (!ValidateAccessMaskPipelineStage(mem_barrier->srcAccessMask, src_stage_mask)) {
6559d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis            skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
6560d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis                            HandleToUint64(cb_state->commandBuffer), __LINE__, VALIDATION_ERROR_1b800940, "DS",
6561d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis                            "%s: pBufferMemBarriers[%d].srcAccessMask (0x%X) is not supported by srcStageMask (0x%X). %s", funcName,
6562d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis                            i, mem_barrier->srcAccessMask, src_stage_mask, validation_error_map[VALIDATION_ERROR_1b800940]);
6563d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis        }
65641ce9b1e7d3dfd0841efede007022bdc960917008Tobin Ehlis        if (!ValidateAccessMaskPipelineStage(mem_barrier->dstAccessMask, dst_stage_mask)) {
65651ce9b1e7d3dfd0841efede007022bdc960917008Tobin Ehlis            skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
65661ce9b1e7d3dfd0841efede007022bdc960917008Tobin Ehlis                            HandleToUint64(cb_state->commandBuffer), __LINE__, VALIDATION_ERROR_1b800942, "DS",
65671ce9b1e7d3dfd0841efede007022bdc960917008Tobin Ehlis                            "%s: pBufferMemBarriers[%d].dstAccessMask (0x%X) is not supported by dstStageMask (0x%X). %s", funcName,
65681ce9b1e7d3dfd0841efede007022bdc960917008Tobin Ehlis                            i, mem_barrier->dstAccessMask, dst_stage_mask, validation_error_map[VALIDATION_ERROR_1b800942]);
65691ce9b1e7d3dfd0841efede007022bdc960917008Tobin Ehlis        }
65705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // Validate buffer barrier queue family indices
65715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if ((mem_barrier->srcQueueFamilyIndex != VK_QUEUE_FAMILY_IGNORED &&
6572e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis             mem_barrier->srcQueueFamilyIndex >= device_data->phys_dev_properties.queue_family_properties.size()) ||
65735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            (mem_barrier->dstQueueFamilyIndex != VK_QUEUE_FAMILY_IGNORED &&
6574e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis             mem_barrier->dstQueueFamilyIndex >= device_data->phys_dev_properties.queue_family_properties.size())) {
6575e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis            skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
6576e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                            HandleToUint64(cb_state->commandBuffer), __LINE__, DRAWSTATE_INVALID_QUEUE_INDEX, "DS",
6577cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                            "%s: Buffer Barrier 0x%" PRIx64
6578cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                            " has QueueFamilyIndex greater "
6579a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis                            "than the number of QueueFamilies (" PRINTF_SIZE_T_SPECIFIER ") for this device.",
65809b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            funcName, HandleToUint64(mem_barrier->buffer),
6581e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                            device_data->phys_dev_properties.queue_family_properties.size());
65825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
65835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
6584e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis        auto buffer_state = GetBufferState(device_data, mem_barrier->buffer);
65855cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis        if (buffer_state) {
65865cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis            auto buffer_size = buffer_state->requirements.size;
65875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (mem_barrier->offset >= buffer_size) {
6588e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                skip |= log_msg(
6589e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                    device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
6590e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                    HandleToUint64(cb_state->commandBuffer), __LINE__, DRAWSTATE_INVALID_BARRIER, "DS",
6591e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                    "%s: Buffer Barrier 0x%" PRIx64 " has offset 0x%" PRIx64 " which is not less than total size 0x%" PRIx64 ".",
6592e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                    funcName, HandleToUint64(mem_barrier->buffer), HandleToUint64(mem_barrier->offset),
6593e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                    HandleToUint64(buffer_size));
6594df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski            } else if (mem_barrier->size != VK_WHOLE_SIZE && (mem_barrier->offset + mem_barrier->size > buffer_size)) {
6595df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                skip |=
6596e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                    log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
6597e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                            HandleToUint64(cb_state->commandBuffer), __LINE__, DRAWSTATE_INVALID_BARRIER, "DS",
6598df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                            "%s: Buffer Barrier 0x%" PRIx64 " has offset 0x%" PRIx64 " and size 0x%" PRIx64
6599df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                            " whose sum is greater than total size 0x%" PRIx64 ".",
66009b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            funcName, HandleToUint64(mem_barrier->buffer), HandleToUint64(mem_barrier->offset),
66019b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(mem_barrier->size), HandleToUint64(buffer_size));
66025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
66035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
66045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
6605a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis    return skip;
66065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
66075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
6608bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskibool validateEventStageMask(VkQueue queue, GLOBAL_CB_NODE *pCB, uint32_t eventCount, size_t firstEventIndex,
6609bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                            VkPipelineStageFlags sourceStageMask) {
66103251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
6611b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine    VkPipelineStageFlags stageMask = 0;
661256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map);
6613b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine    for (uint32_t i = 0; i < eventCount; ++i) {
66142ab14387df9b890fe4b13494ea249dd03cf898d2Chris Forbes        auto event = pCB->events[firstEventIndex + i];
6615b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine        auto queue_data = dev_data->queueMap.find(queue);
6616cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        if (queue_data == dev_data->queueMap.end()) return false;
66172ab14387df9b890fe4b13494ea249dd03cf898d2Chris Forbes        auto event_data = queue_data->second.eventToStageMap.find(event);
6618b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine        if (event_data != queue_data->second.eventToStageMap.end()) {
6619b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine            stageMask |= event_data->second;
6620b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine        } else {
66219a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            auto global_event_data = GetEventNode(dev_data, event);
66229556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis            if (!global_event_data) {
66233251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT,
66249b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                HandleToUint64(event), __LINE__, DRAWSTATE_INVALID_EVENT, "DS",
66259b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                "Event 0x%" PRIx64 " cannot be waited on if it has never been set.", HandleToUint64(event));
6626b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine            } else {
66279556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis                stageMask |= global_event_data->stageMask;
6628b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine            }
6629b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine        }
6630b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine    }
6631c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine    // TODO: Need to validate that host_bit is only set if set event is called
6632c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine    // but set event can be called at any time.
6633c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine    if (sourceStageMask != stageMask && sourceStageMask != (stageMask | VK_PIPELINE_STAGE_HOST_BIT)) {
66343251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
6635315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(pCB->commandBuffer), __LINE__, VALIDATION_ERROR_1e62d401, "DS",
66363251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "Submitting cmdbuffer with call to VkCmdWaitEvents "
66373251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "using srcStageMask 0x%X which must be the bitwise "
66383251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "OR of the stageMask parameters used in calls to "
66393251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "vkCmdSetEvent and VK_PIPELINE_STAGE_HOST_BIT if "
66403251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "used with vkSetEvent but instead is 0x%X. %s",
6641315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        sourceStageMask, stageMask, validation_error_map[VALIDATION_ERROR_1e62d401]);
6642b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine    }
66433251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
6644b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine}
6645b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine
664607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski// Note that we only check bits that HAVE required queueflags -- don't care entries are skipped
664707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinskistatic std::unordered_map<VkPipelineStageFlags, VkQueueFlags> supported_pipeline_stages_table = {
664807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    {VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX, VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT},
664907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    {VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT},
665007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    {VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_QUEUE_GRAPHICS_BIT},
665107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    {VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, VK_QUEUE_GRAPHICS_BIT},
665207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    {VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT, VK_QUEUE_GRAPHICS_BIT},
665307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    {VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT, VK_QUEUE_GRAPHICS_BIT},
665407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    {VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT, VK_QUEUE_GRAPHICS_BIT},
665507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    {VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_QUEUE_GRAPHICS_BIT},
665607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    {VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, VK_QUEUE_GRAPHICS_BIT},
665707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    {VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_QUEUE_GRAPHICS_BIT},
665807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_QUEUE_GRAPHICS_BIT},
665907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    {VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_QUEUE_COMPUTE_BIT},
666007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    {VK_PIPELINE_STAGE_TRANSFER_BIT, VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT},
666107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    {VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_QUEUE_GRAPHICS_BIT}};
666207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski
666307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinskistatic const VkPipelineStageFlags stage_flag_bit_array[] = {VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX,
666407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                                                            VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT,
666507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                                                            VK_PIPELINE_STAGE_VERTEX_INPUT_BIT,
666607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                                                            VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,
666707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                                                            VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT,
666807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                                                            VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT,
666907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                                                            VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT,
667007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                                                            VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
667107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                                                            VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,
667207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                                                            VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
667307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                                                            VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
667407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                                                            VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
667507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                                                            VK_PIPELINE_STAGE_TRANSFER_BIT,
667607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                                                            VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT};
667707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski
667807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinskibool CheckStageMaskQueueCompatibility(layer_data *dev_data, VkCommandBuffer command_buffer, VkPipelineStageFlags stage_mask,
667907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                                      VkQueueFlags queue_flags, const char *function, const char *src_or_dest,
668007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                                      UNIQUE_VALIDATION_ERROR_CODE error_code) {
668107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    bool skip = false;
668207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    // Lookup each bit in the stagemask and check for overlap between its table bits and queue_flags
668307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    for (const auto &item : stage_flag_bit_array) {
668407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski        if (stage_mask & item) {
668507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski            if ((supported_pipeline_stages_table[item] & queue_flags) == 0) {
668607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                skip |=
668707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
66889b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(command_buffer), __LINE__, error_code, "DL",
668907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                            "%s(): %s flag %s is not compatible with the queue family properties of this "
669007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                            "command buffer. %s",
669107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                            function, src_or_dest, string_VkPipelineStageFlagBits(static_cast<VkPipelineStageFlagBits>(item)),
669207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                            validation_error_map[error_code]);
669307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski            }
669407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski        }
669507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    }
669607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    return skip;
669707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski}
669807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski
6699e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlisbool ValidateStageMasksAgainstQueueCapabilities(layer_data *dev_data, GLOBAL_CB_NODE const *cb_state,
670007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                                                VkPipelineStageFlags source_stage_mask, VkPipelineStageFlags dest_stage_mask,
670107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                                                const char *function, UNIQUE_VALIDATION_ERROR_CODE error_code) {
670207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    bool skip = false;
670307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    uint32_t queue_family_index = dev_data->commandPoolMap[cb_state->createInfo.commandPool].queueFamilyIndex;
670456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(dev_data->physical_device), instance_layer_data_map);
67059a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto physical_device_state = GetPhysicalDeviceState(instance_data, dev_data->physical_device);
670607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski
670707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    // Any pipeline stage included in srcStageMask or dstStageMask must be supported by the capabilities of the queue family
670807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    // specified by the queueFamilyIndex member of the VkCommandPoolCreateInfo structure that was used to create the VkCommandPool
670907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    // that commandBuffer was allocated from, as specified in the table of supported pipeline stages.
671007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski
671107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    if (queue_family_index < physical_device_state->queue_family_properties.size()) {
671207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski        VkQueueFlags specified_queue_flags = physical_device_state->queue_family_properties[queue_family_index].queueFlags;
671307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski
671407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski        if ((source_stage_mask & VK_PIPELINE_STAGE_ALL_COMMANDS_BIT) == 0) {
671507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski            skip |= CheckStageMaskQueueCompatibility(dev_data, cb_state->commandBuffer, source_stage_mask, specified_queue_flags,
671607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                                                     function, "srcStageMask", error_code);
671707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski        }
671807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski        if ((dest_stage_mask & VK_PIPELINE_STAGE_ALL_COMMANDS_BIT) == 0) {
671907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski            skip |= CheckStageMaskQueueCompatibility(dev_data, cb_state->commandBuffer, dest_stage_mask, specified_queue_flags,
672007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                                                     function, "dstStageMask", error_code);
672107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski        }
672207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    }
672307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    return skip;
672407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski}
672507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski
6726d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent *pEvents,
6727d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski                                         VkPipelineStageFlags sourceStageMask, VkPipelineStageFlags dstStageMask,
6728d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski                                         uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
6729d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski                                         uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers,
6730d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski                                         uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers) {
6731d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski    bool skip = false;
673256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
6733ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
67349a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer);
6735d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski    if (cb_state) {
6736d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski        skip |= ValidateStageMasksAgainstQueueCapabilities(dev_data, cb_state, sourceStageMask, dstStageMask, "vkCmdWaitEvents",
6737315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                                           VALIDATION_ERROR_1e600918);
6738315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= ValidateStageMaskGsTsEnables(dev_data, sourceStageMask, "vkCmdWaitEvents()", VALIDATION_ERROR_1e60090e,
6739315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                             VALIDATION_ERROR_1e600912);
6740315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= ValidateStageMaskGsTsEnables(dev_data, dstStageMask, "vkCmdWaitEvents()", VALIDATION_ERROR_1e600910,
6741315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                             VALIDATION_ERROR_1e600914);
6742d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski        auto first_event_index = cb_state->events.size();
67435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t i = 0; i < eventCount; ++i) {
67449a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            auto event_state = GetEventNode(dev_data, pEvents[i]);
67454710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis            if (event_state) {
67469b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                addCommandBufferBinding(&event_state->cb_bindings, {HandleToUint64(pEvents[i]), kVulkanObjectTypeEvent}, cb_state);
6747d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski                event_state->cb_bindings.insert(cb_state);
6748ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis            }
6749d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski            cb_state->waitedEvents.insert(pEvents[i]);
6750d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski            cb_state->events.push_back(pEvents[i]);
67515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
6752f49bd2b5f4c968a3033b3e5099bbbcff51201575Chris Forbes        cb_state->eventUpdates.emplace_back([=](VkQueue q){
6753f49bd2b5f4c968a3033b3e5099bbbcff51201575Chris Forbes            return validateEventStageMask(q, cb_state, eventCount, first_event_index, sourceStageMask);
6754f49bd2b5f4c968a3033b3e5099bbbcff51201575Chris Forbes        });
6755baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt        skip |= ValidateCmdQueueFlags(dev_data, cb_state, "vkCmdWaitEvents()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT,
6756315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                      VALIDATION_ERROR_1e602415);
6757ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski        skip |= ValidateCmd(dev_data, cb_state, CMD_WAITEVENTS, "vkCmdWaitEvents()");
6758e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis        skip |= ValidateBarriersToImages(dev_data, cb_state, imageMemoryBarrierCount, pImageMemoryBarriers, "vkCmdWaitEvents()");
6759e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski        if (!skip) {
6760e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski            TransitionImageLayouts(dev_data, commandBuffer, imageMemoryBarrierCount, pImageMemoryBarriers);
6761e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski        }
6762e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis        skip |= ValidateBarriers(dev_data, "vkCmdWaitEvents()", cb_state, sourceStageMask, dstStageMask, memoryBarrierCount,
6763e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                                 pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount,
6764e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                                 pImageMemoryBarriers);
67655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
6766b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
6767d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski    if (!skip)
67684a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdWaitEvents(commandBuffer, eventCount, pEvents, sourceStageMask, dstStageMask,
67694a0754042cf090e131e9e769d8a3633c228625beChris Forbes                                               memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers,
67704a0754042cf090e131e9e769d8a3633c228625beChris Forbes                                               imageMemoryBarrierCount, pImageMemoryBarriers);
67715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
67725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
6773f384f33742c2b72888372332747298d08135ac92Tobin Ehlisstatic bool PreCallValidateCmdPipelineBarrier(layer_data *device_data, GLOBAL_CB_NODE *cb_state, VkPipelineStageFlags srcStageMask,
6774f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                                              VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags,
6775f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                                              uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
6776f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                                              uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers,
6777f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                                              uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers) {
677803122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski    bool skip = false;
677903122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski    skip |= ValidateStageMasksAgainstQueueCapabilities(device_data, cb_state, srcStageMask, dstStageMask, "vkCmdPipelineBarrier",
6780315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                                       VALIDATION_ERROR_1b80093e);
6781baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt    skip |= ValidateCmdQueueFlags(device_data, cb_state, "vkCmdPipelineBarrier()",
6782315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                  VK_QUEUE_TRANSFER_BIT | VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, VALIDATION_ERROR_1b802415);
678303122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski    skip |= ValidateCmd(device_data, cb_state, CMD_PIPELINEBARRIER, "vkCmdPipelineBarrier()");
6784315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis    skip |= ValidateStageMaskGsTsEnables(device_data, srcStageMask, "vkCmdPipelineBarrier()", VALIDATION_ERROR_1b800920,
6785315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                         VALIDATION_ERROR_1b800924);
6786315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis    skip |= ValidateStageMaskGsTsEnables(device_data, dstStageMask, "vkCmdPipelineBarrier()", VALIDATION_ERROR_1b800922,
6787315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                         VALIDATION_ERROR_1b800926);
6788e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis    if (cb_state->activeRenderPass) {
6789e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis        skip |= ValidateRenderPassPipelineBarriers(device_data, "vkCmdPipelineBarrier()", cb_state, srcStageMask, dstStageMask,
6790c1c43cc01e333f3762c65ce4ad926c33235583d2Tobin Ehlis                                                   dependencyFlags, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount,
6791e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                                                   pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers);
6792a287b10c55baa7d2d2ac891eb729666f988766eaTobin Ehlis        if (skip) return true;  // Early return to avoid redundant errors from below calls
6793e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis    }
6794a287b10c55baa7d2d2ac891eb729666f988766eaTobin Ehlis    skip |=
6795a287b10c55baa7d2d2ac891eb729666f988766eaTobin Ehlis        ValidateBarriersToImages(device_data, cb_state, imageMemoryBarrierCount, pImageMemoryBarriers, "vkCmdPipelineBarrier()");
6796e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis    skip |= ValidateBarriers(device_data, "vkCmdPipelineBarrier()", cb_state, srcStageMask, dstStageMask, memoryBarrierCount,
6797e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                             pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount,
6798e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                             pImageMemoryBarriers);
679903122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski    return skip;
680003122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski}
680103122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski
68026f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinskistatic void PreCallRecordCmdPipelineBarrier(layer_data *device_data, GLOBAL_CB_NODE *cb_state, VkCommandBuffer commandBuffer,
68036f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski                                            uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers) {
68046f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski    TransitionImageLayouts(device_data, commandBuffer, imageMemoryBarrierCount, pImageMemoryBarriers);
68056f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski}
68066f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski
6807d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdPipelineBarrier(VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask,
6808d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski                                              VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags,
6809d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski                                              uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
6810d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski                                              uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers,
6811d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski                                              uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers) {
6812d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski    bool skip = false;
68136f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski    layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
6814ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
68156f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski    GLOBAL_CB_NODE *cb_state = GetCBNode(device_data, commandBuffer);
6816d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski    if (cb_state) {
6817c1c43cc01e333f3762c65ce4ad926c33235583d2Tobin Ehlis        skip |= PreCallValidateCmdPipelineBarrier(device_data, cb_state, srcStageMask, dstStageMask, dependencyFlags,
6818c1c43cc01e333f3762c65ce4ad926c33235583d2Tobin Ehlis                                                  memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount,
6819c1c43cc01e333f3762c65ce4ad926c33235583d2Tobin Ehlis                                                  pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers);
68206f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski        if (!skip) {
68216f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski            PreCallRecordCmdPipelineBarrier(device_data, cb_state, commandBuffer, imageMemoryBarrierCount, pImageMemoryBarriers);
68226f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski        }
68236f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski    } else {
68246f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski        assert(0);
68255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
6826b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
6827a79957f762f6fc6b74c25cb94d35a3fc36967471Tony Barbour    if (!skip) {
6828a79957f762f6fc6b74c25cb94d35a3fc36967471Tony Barbour        device_data->dispatch_table.CmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, memoryBarrierCount,
6829a79957f762f6fc6b74c25cb94d35a3fc36967471Tony Barbour                                                       pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers,
6830a79957f762f6fc6b74c25cb94d35a3fc36967471Tony Barbour                                                       imageMemoryBarrierCount, pImageMemoryBarriers);
6831a79957f762f6fc6b74c25cb94d35a3fc36967471Tony Barbour    }
68325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
68335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
683443ec3f090ca979777b306abe7c25662b9429e06dChris Forbesstatic bool setQueryState(VkQueue queue, VkCommandBuffer commandBuffer, QueryObject object, bool value) {
683556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
68369a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer);
6837d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine    if (pCB) {
6838d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine        pCB->queryToStateMap[object] = value;
6839d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine    }
6840d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine    auto queue_data = dev_data->queueMap.find(queue);
6841d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine    if (queue_data != dev_data->queueMap.end()) {
6842d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine        queue_data->second.queryToStateMap[object] = value;
6843d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine    }
6844d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine    return false;
6845d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine}
6846d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine
6847bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBeginQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t slot, VkFlags flags) {
68483251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
684956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
6850ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
68519a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer);
68525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
68533251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdBeginQuery()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT,
6854315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                      VALIDATION_ERROR_17802415);
68553251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateCmd(dev_data, pCB, CMD_BEGINQUERY, "vkCmdBeginQuery()");
685643ec3f090ca979777b306abe7c25662b9429e06dChris Forbes    }
685743ec3f090ca979777b306abe7c25662b9429e06dChris Forbes    lock.unlock();
685843ec3f090ca979777b306abe7c25662b9429e06dChris Forbes
685943ec3f090ca979777b306abe7c25662b9429e06dChris Forbes    if (skip) return;
686043ec3f090ca979777b306abe7c25662b9429e06dChris Forbes
686143ec3f090ca979777b306abe7c25662b9429e06dChris Forbes    dev_data->dispatch_table.CmdBeginQuery(commandBuffer, queryPool, slot, flags);
686243ec3f090ca979777b306abe7c25662b9429e06dChris Forbes
686343ec3f090ca979777b306abe7c25662b9429e06dChris Forbes    lock.lock();
686443ec3f090ca979777b306abe7c25662b9429e06dChris Forbes    if (pCB) {
686543ec3f090ca979777b306abe7c25662b9429e06dChris Forbes        QueryObject query = {queryPool, slot};
686643ec3f090ca979777b306abe7c25662b9429e06dChris Forbes        pCB->activeQueries.insert(query);
686743ec3f090ca979777b306abe7c25662b9429e06dChris Forbes        pCB->startedQueries.insert(query);
68689a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        addCommandBufferBinding(&GetQueryPoolNode(dev_data, queryPool)->cb_bindings,
68699b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                {HandleToUint64(queryPool), kVulkanObjectTypeQueryPool}, pCB);
68705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
68715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
68725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
687389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdEndQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t slot) {
6874946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski    bool skip = false;
687556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
6876ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
6877e17228238940d38a82570bc5b0ed4dd44e4cbd6dChris Forbes    QueryObject query = {queryPool, slot};
6878946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski    GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer);
6879946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski    if (cb_state) {
6880946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski        if (!cb_state->activeQueries.count(query)) {
6881df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
6882315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_1ae00652, "DS",
68839b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            "Ending a query before it was started: queryPool 0x%" PRIx64 ", index %d. %s",
6884315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(queryPool), slot, validation_error_map[VALIDATION_ERROR_1ae00652]);
68855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
6886baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt        skip |= ValidateCmdQueueFlags(dev_data, cb_state, "VkCmdEndQuery()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT,
6887315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                      VALIDATION_ERROR_1ae02415);
6888946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski        skip |= ValidateCmd(dev_data, cb_state, CMD_ENDQUERY, "VkCmdEndQuery()");
6889e17228238940d38a82570bc5b0ed4dd44e4cbd6dChris Forbes    }
6890e17228238940d38a82570bc5b0ed4dd44e4cbd6dChris Forbes    lock.unlock();
6891e17228238940d38a82570bc5b0ed4dd44e4cbd6dChris Forbes
6892e17228238940d38a82570bc5b0ed4dd44e4cbd6dChris Forbes    if (skip) return;
6893e17228238940d38a82570bc5b0ed4dd44e4cbd6dChris Forbes
6894e17228238940d38a82570bc5b0ed4dd44e4cbd6dChris Forbes    dev_data->dispatch_table.CmdEndQuery(commandBuffer, queryPool, slot);
6895e17228238940d38a82570bc5b0ed4dd44e4cbd6dChris Forbes
6896e17228238940d38a82570bc5b0ed4dd44e4cbd6dChris Forbes    lock.lock();
6897e17228238940d38a82570bc5b0ed4dd44e4cbd6dChris Forbes    if (cb_state) {
6898e17228238940d38a82570bc5b0ed4dd44e4cbd6dChris Forbes        cb_state->activeQueries.erase(query);
6899e17228238940d38a82570bc5b0ed4dd44e4cbd6dChris Forbes        cb_state->queryUpdates.emplace_back([=](VkQueue q){return setQueryState(q, commandBuffer, query, true);});
69009a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        addCommandBufferBinding(&GetQueryPoolNode(dev_data, queryPool)->cb_bindings,
69019b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                {HandleToUint64(queryPool), kVulkanObjectTypeQueryPool}, cb_state);
69025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
69035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
69045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
6905bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdResetQueryPool(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery,
6906bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                             uint32_t queryCount) {
6907946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski    bool skip = false;
690856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
6909ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
6910946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski    GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer);
69113a4c679ed508b10fd119bb97c127c79b5d126d74Chris Forbes        skip |= insideRenderPass(dev_data, cb_state, "vkCmdResetQueryPool()", VALIDATION_ERROR_1c600017);
69123a4c679ed508b10fd119bb97c127c79b5d126d74Chris Forbes        skip |= ValidateCmd(dev_data, cb_state, CMD_RESETQUERYPOOL, "VkCmdResetQueryPool()");
6913baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt        skip |= ValidateCmdQueueFlags(dev_data, cb_state, "VkCmdResetQueryPool()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT,
6914315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                      VALIDATION_ERROR_1c602415);
6915b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
69163a4c679ed508b10fd119bb97c127c79b5d126d74Chris Forbes
69173a4c679ed508b10fd119bb97c127c79b5d126d74Chris Forbes    if (skip) return;
69183a4c679ed508b10fd119bb97c127c79b5d126d74Chris Forbes
69193a4c679ed508b10fd119bb97c127c79b5d126d74Chris Forbes    dev_data->dispatch_table.CmdResetQueryPool(commandBuffer, queryPool, firstQuery, queryCount);
69203a4c679ed508b10fd119bb97c127c79b5d126d74Chris Forbes
69213a4c679ed508b10fd119bb97c127c79b5d126d74Chris Forbes    lock.lock();
69223a4c679ed508b10fd119bb97c127c79b5d126d74Chris Forbes    for (uint32_t i = 0; i < queryCount; i++) {
69233a4c679ed508b10fd119bb97c127c79b5d126d74Chris Forbes        QueryObject query = {queryPool, firstQuery + i};
69243a4c679ed508b10fd119bb97c127c79b5d126d74Chris Forbes        cb_state->waitedEventsBeforeQueryReset[query] = cb_state->waitedEvents;
6925f49bd2b5f4c968a3033b3e5099bbbcff51201575Chris Forbes        cb_state->queryUpdates.emplace_back([=](VkQueue q){return setQueryState(q, commandBuffer, query, false);});
69263a4c679ed508b10fd119bb97c127c79b5d126d74Chris Forbes    }
69273a4c679ed508b10fd119bb97c127c79b5d126d74Chris Forbes    addCommandBufferBinding(&GetQueryPoolNode(dev_data, queryPool)->cb_bindings,
69283a4c679ed508b10fd119bb97c127c79b5d126d74Chris Forbes                            {HandleToUint64(queryPool), kVulkanObjectTypeQueryPool}, cb_state);
69295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
69305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
69317ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbesstatic bool IsQueryInvalid(layer_data *dev_data, QUEUE_STATE *queue_data, VkQueryPool queryPool, uint32_t queryIndex) {
69327ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes    QueryObject query = {queryPool, queryIndex};
69337ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes    auto query_data = queue_data->queryToStateMap.find(query);
69347ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes    if (query_data != queue_data->queryToStateMap.end()) {
69357ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes        if (!query_data->second) return true;
69367ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes    } else {
69377ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes        auto it = dev_data->queryToStateMap.find(query);
69387ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes        if (it == dev_data->queryToStateMap.end() || !it->second)
69397ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes            return true;
69407ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes    }
69417ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes
69427ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes    return false;
69437ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes}
69447ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes
69457ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbesstatic bool validateQuery(VkQueue queue, GLOBAL_CB_NODE *pCB, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount) {
69463251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
694756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(pCB->commandBuffer), layer_data_map);
69487ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes    auto queue_data = GetQueueState(dev_data, queue);
69497ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes    if (!queue_data) return false;
6950d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine    for (uint32_t i = 0; i < queryCount; i++) {
69517ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes        if (IsQueryInvalid(dev_data, queue_data, queryPool, firstQuery + i)) {
69523251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
69539b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_QUERY, "DS",
69543251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "Requesting a copy from query to buffer with invalid query: queryPool 0x%" PRIx64 ", index %d",
69559b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(queryPool), firstQuery + i);
6956d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine        }
6957d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine    }
69583251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
6959d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine}
6960d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine
6961bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdCopyQueryPoolResults(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery,
6962bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                   uint32_t queryCount, VkBuffer dstBuffer, VkDeviceSize dstOffset,
6963bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                   VkDeviceSize stride, VkQueryResultFlags flags) {
6964946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski    bool skip = false;
696556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
6966ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
6967ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis
69689a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto cb_node = GetCBNode(dev_data, commandBuffer);
69699a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto dst_buff_state = GetBufferState(dev_data, dstBuffer);
69705cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis    if (cb_node && dst_buff_state) {
6971315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= ValidateMemoryIsBoundToBuffer(dev_data, dst_buff_state, "vkCmdCopyQueryPoolResults()", VALIDATION_ERROR_19400674);
6972ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        // Validate that DST buffer has correct usage flags set
6973315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |=
6974315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis            ValidateBufferUsageFlags(dev_data, dst_buff_state, VK_BUFFER_USAGE_TRANSFER_DST_BIT, true, VALIDATION_ERROR_19400672,
6975315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                     "vkCmdCopyQueryPoolResults()", "VK_BUFFER_USAGE_TRANSFER_DST_BIT");
69764d285deca53ab503c0c9eb65ba1c4fb711138d7cChris Forbes        skip |= ValidateCmdQueueFlags(dev_data, cb_node, "vkCmdCopyQueryPoolResults()",
69774d285deca53ab503c0c9eb65ba1c4fb711138d7cChris Forbes                                      VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, VALIDATION_ERROR_19402415);
69784d285deca53ab503c0c9eb65ba1c4fb711138d7cChris Forbes        skip |= ValidateCmd(dev_data, cb_node, CMD_COPYQUERYPOOLRESULTS, "vkCmdCopyQueryPoolResults()");
69794d285deca53ab503c0c9eb65ba1c4fb711138d7cChris Forbes        skip |= insideRenderPass(dev_data, cb_node, "vkCmdCopyQueryPoolResults()", VALIDATION_ERROR_19400017);
69804d285deca53ab503c0c9eb65ba1c4fb711138d7cChris Forbes    }
69814d285deca53ab503c0c9eb65ba1c4fb711138d7cChris Forbes    lock.unlock();
69824d285deca53ab503c0c9eb65ba1c4fb711138d7cChris Forbes
69834d285deca53ab503c0c9eb65ba1c4fb711138d7cChris Forbes    if (skip) return;
69844d285deca53ab503c0c9eb65ba1c4fb711138d7cChris Forbes
69854d285deca53ab503c0c9eb65ba1c4fb711138d7cChris Forbes    dev_data->dispatch_table.CmdCopyQueryPoolResults(commandBuffer, queryPool, firstQuery, queryCount, dstBuffer, dstOffset,
69864d285deca53ab503c0c9eb65ba1c4fb711138d7cChris Forbes                                                     stride, flags);
69874d285deca53ab503c0c9eb65ba1c4fb711138d7cChris Forbes
69884d285deca53ab503c0c9eb65ba1c4fb711138d7cChris Forbes    lock.lock();
69894d285deca53ab503c0c9eb65ba1c4fb711138d7cChris Forbes    if (cb_node && dst_buff_state) {
69904d285deca53ab503c0c9eb65ba1c4fb711138d7cChris Forbes        AddCommandBufferBindingBuffer(dev_data, cb_node, dst_buff_state);
69914d285deca53ab503c0c9eb65ba1c4fb711138d7cChris Forbes        cb_node->validate_functions.emplace_back([=]() {
69925cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis            SetBufferMemoryValid(dev_data, dst_buff_state, true);
6993e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves            return false;
69944d285deca53ab503c0c9eb65ba1c4fb711138d7cChris Forbes        });
6995f49bd2b5f4c968a3033b3e5099bbbcff51201575Chris Forbes        cb_node->queryUpdates.emplace_back([=](VkQueue q) {
6996f49bd2b5f4c968a3033b3e5099bbbcff51201575Chris Forbes            return validateQuery(q, cb_node, queryPool, firstQuery, queryCount);
6997f49bd2b5f4c968a3033b3e5099bbbcff51201575Chris Forbes        });
69989a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        addCommandBufferBinding(&GetQueryPoolNode(dev_data, queryPool)->cb_bindings,
69999b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                {HandleToUint64(queryPool), kVulkanObjectTypeQueryPool}, cb_node);
70005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
70015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
70025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
7003bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdPushConstants(VkCommandBuffer commandBuffer, VkPipelineLayout layout, VkShaderStageFlags stageFlags,
7004bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                            uint32_t offset, uint32_t size, const void *pValues) {
7005946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski    bool skip = false;
700656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
7007ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
7008946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski    GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer);
7009946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski    if (cb_state) {
7010baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt        skip |= ValidateCmdQueueFlags(dev_data, cb_state, "vkCmdPushConstants()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT,
7011315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                      VALIDATION_ERROR_1bc02415);
7012946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski        skip |= ValidateCmd(dev_data, cb_state, CMD_PUSHCONSTANTS, "vkCmdPushConstants()");
70135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
7014946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski    skip |= validatePushConstantRange(dev_data, offset, size, "vkCmdPushConstants()");
70159e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz    if (0 == stageFlags) {
7016df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
7017315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_1bc2dc03, "DS",
7018315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        "vkCmdPushConstants() call has no stageFlags set. %s", validation_error_map[VALIDATION_ERROR_1bc2dc03]);
70199e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz    }
70209e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz
7021bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz    // Check if specified push constant range falls within a pipeline-defined range which has matching stageFlags.
7022bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz    // The spec doesn't seem to disallow having multiple push constant ranges with the
7023bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz    // same offset and size, but different stageFlags.  So we can't just check the
7024bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz    // stageFlags in the first range with matching offset and size.
7025bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz    if (!skip) {
7026bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz        const auto &ranges = getPipelineLayout(dev_data, layout)->push_constant_ranges;
7027bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz        bool found_matching_range = false;
7028bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz        for (const auto &range : ranges) {
7029bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz            if ((stageFlags == range.stageFlags) && (offset >= range.offset) && (offset + size <= range.offset + range.size)) {
7030bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz                found_matching_range = true;
703115a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis                break;
7032a95cb74c9d0947ab3821b15e1289755286ea78eeKarl Schultz            }
70339e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        }
7034bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz        if (!found_matching_range) {
7035315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
7036315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_1bc002de, "DS",
7037315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            "vkCmdPushConstants() stageFlags = 0x%" PRIx32
7038315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            " do not match the stageFlags in any of the ranges with"
7039315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            " offset = %d and size = %d in pipeline layout 0x%" PRIx64 ". %s",
7040315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            (uint32_t)stageFlags, offset, size, HandleToUint64(layout),
7041315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            validation_error_map[VALIDATION_ERROR_1bc002de]);
704215a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis        }
70435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
7044b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
7045946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski    if (!skip) dev_data->dispatch_table.CmdPushConstants(commandBuffer, layout, stageFlags, offset, size, pValues);
70465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
70475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
7048bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdWriteTimestamp(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage,
7049bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                             VkQueryPool queryPool, uint32_t slot) {
7050946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski    bool skip = false;
705156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
7052ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
7053946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski    GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer);
7054946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski    if (cb_state) {
7055baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt        skip |= ValidateCmdQueueFlags(dev_data, cb_state, "vkCmdWriteTimestamp()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT,
7056315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                      VALIDATION_ERROR_1e802415);
7057946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski        skip |= ValidateCmd(dev_data, cb_state, CMD_WRITETIMESTAMP, "vkCmdWriteTimestamp()");
70585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
7059b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
70606eff586acc3c02decfb0c3af269693252efc8ef8Chris Forbes
70616eff586acc3c02decfb0c3af269693252efc8ef8Chris Forbes    if (skip) return;
70626eff586acc3c02decfb0c3af269693252efc8ef8Chris Forbes
70636eff586acc3c02decfb0c3af269693252efc8ef8Chris Forbes    dev_data->dispatch_table.CmdWriteTimestamp(commandBuffer, pipelineStage, queryPool, slot);
70646eff586acc3c02decfb0c3af269693252efc8ef8Chris Forbes
70656eff586acc3c02decfb0c3af269693252efc8ef8Chris Forbes    lock.lock();
70666eff586acc3c02decfb0c3af269693252efc8ef8Chris Forbes    if (cb_state) {
70676eff586acc3c02decfb0c3af269693252efc8ef8Chris Forbes        QueryObject query = {queryPool, slot};
70686eff586acc3c02decfb0c3af269693252efc8ef8Chris Forbes        cb_state->queryUpdates.emplace_back([=](VkQueue q) {return setQueryState(q, commandBuffer, query, true);});
70696eff586acc3c02decfb0c3af269693252efc8ef8Chris Forbes    }
70705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
70715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
70726600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinskistatic bool MatchUsage(layer_data *dev_data, uint32_t count, const VkAttachmentReference *attachments,
70739bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt                       const VkFramebufferCreateInfo *fbci, VkImageUsageFlagBits usage_flag,
70749bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt                       UNIQUE_VALIDATION_ERROR_CODE error_code) {
7075946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski    bool skip = false;
70766600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski
70776600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski    for (uint32_t attach = 0; attach < count; attach++) {
70786600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski        if (attachments[attach].attachment != VK_ATTACHMENT_UNUSED) {
70796600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski            // Attachment counts are verified elsewhere, but prevent an invalid access
70806600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski            if (attachments[attach].attachment < fbci->attachmentCount) {
70816600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski                const VkImageView *image_view = &fbci->pAttachments[attachments[attach].attachment];
70829a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                auto view_state = GetImageViewState(dev_data, *image_view);
708379fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis                if (view_state) {
70849a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                    const VkImageCreateInfo *ici = &GetImageState(dev_data, view_state->create_info.image)->createInfo;
70856600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski                    if (ici != nullptr) {
70866600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski                        if ((ici->usage & usage_flag) == 0) {
7087df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
7088df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                                            VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, error_code, "DS",
7089946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski                                            "vkCreateFramebuffer:  Framebuffer Attachment (%d) conflicts with the image's "
7090946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski                                            "IMAGE_USAGE flags (%s). %s",
7091946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski                                            attachments[attach].attachment, string_VkImageUsageFlagBits(usage_flag),
7092946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski                                            validation_error_map[error_code]);
70936600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski                        }
70946600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski                    }
70956600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski                }
70966600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski            }
70976600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski        }
70986600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski    }
7099946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski    return skip;
71006600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski}
71016600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski
7102d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis// Validate VkFramebufferCreateInfo which includes:
7103d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis// 1. attachmentCount equals renderPass attachmentCount
71045ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 2. corresponding framebuffer and renderpass attachments have matching formats
71055ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 3. corresponding framebuffer and renderpass attachments have matching sample counts
71065ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 4. fb attachments only have a single mip level
71075ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 5. fb attachment dimensions are each at least as large as the fb
71085ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 6. fb attachments use idenity swizzle
71095ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 7. fb attachments used by renderPass for color/input/ds have correct usage bit set
71106fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis// 8. fb dimensions are within physical device limits
7111d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlisstatic bool ValidateFramebufferCreateInfo(layer_data *dev_data, const VkFramebufferCreateInfo *pCreateInfo) {
71123251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
71136600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski
71149a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto rp_state = GetRenderPassState(dev_data, pCreateInfo->renderPass);
7115127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis    if (rp_state) {
7116127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis        const VkRenderPassCreateInfo *rpci = rp_state->createInfo.ptr();
7117d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis        if (rpci->attachmentCount != pCreateInfo->attachmentCount) {
71183251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(
7119d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis                dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT,
7120315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                HandleToUint64(pCreateInfo->renderPass), __LINE__, VALIDATION_ERROR_094006d8, "DS",
7121d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis                "vkCreateFramebuffer(): VkFramebufferCreateInfo attachmentCount of %u does not match attachmentCount of %u of "
71229bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt                "renderPass (0x%" PRIxLEAST64 ") being used to create Framebuffer. %s",
71239b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                pCreateInfo->attachmentCount, rpci->attachmentCount, HandleToUint64(pCreateInfo->renderPass),
7124315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                validation_error_map[VALIDATION_ERROR_094006d8]);
71255ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis        } else {
712641ebcb6b517b1de5ae456d46d866f5e84a96a2c5Tobin Ehlis            // attachmentCounts match, so make sure corresponding attachment details line up
71275ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis            const VkImageView *image_views = pCreateInfo->pAttachments;
71285ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis            for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) {
71299a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                auto view_state = GetImageViewState(dev_data, image_views[i]);
713012d5600c2f9e32343016fd944432ba95df370797Tobin Ehlis                auto &ivci = view_state->create_info;
713179fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis                if (ivci.format != rpci->pAttachments[i].format) {
71323251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= log_msg(
71335ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis                        dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT,
7134315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(pCreateInfo->renderPass), __LINE__, VALIDATION_ERROR_094006e0, "DS",
71359bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt                        "vkCreateFramebuffer(): VkFramebufferCreateInfo attachment #%u has format of %s that does not match "
71369bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt                        "the format of "
71379bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt                        "%s used by the corresponding attachment for renderPass (0x%" PRIxLEAST64 "). %s",
713879fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis                        i, string_VkFormat(ivci.format), string_VkFormat(rpci->pAttachments[i].format),
7139315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(pCreateInfo->renderPass), validation_error_map[VALIDATION_ERROR_094006e0]);
71405ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis                }
71419a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                const VkImageCreateInfo *ici = &GetImageState(dev_data, ivci.image)->createInfo;
71425ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis                if (ici->samples != rpci->pAttachments[i].samples) {
71433251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= log_msg(
714441ebcb6b517b1de5ae456d46d866f5e84a96a2c5Tobin Ehlis                        dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT,
7145315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(pCreateInfo->renderPass), __LINE__, VALIDATION_ERROR_094006e2, "DS",
71469bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt                        "vkCreateFramebuffer(): VkFramebufferCreateInfo attachment #%u has %s samples that do not match "
71479bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt                        "the %s samples used by the corresponding attachment for renderPass (0x%" PRIxLEAST64 "). %s",
714841ebcb6b517b1de5ae456d46d866f5e84a96a2c5Tobin Ehlis                        i, string_VkSampleCountFlagBits(ici->samples), string_VkSampleCountFlagBits(rpci->pAttachments[i].samples),
7149315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(pCreateInfo->renderPass), validation_error_map[VALIDATION_ERROR_094006e2]);
71505ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis                }
71515ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis                // Verify that view only has a single mip level
715279fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis                if (ivci.subresourceRange.levelCount != 1) {
71533251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT,
7154315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    0, __LINE__, VALIDATION_ERROR_094006e6, "DS",
71553251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    "vkCreateFramebuffer(): VkFramebufferCreateInfo attachment #%u has mip levelCount of %u "
71563251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    "but only a single mip level (levelCount ==  1) is allowed when creating a Framebuffer. %s",
7157315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    i, ivci.subresourceRange.levelCount, validation_error_map[VALIDATION_ERROR_094006e6]);
71585ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis                }
715979fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis                const uint32_t mip_level = ivci.subresourceRange.baseMipLevel;
7160aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis                uint32_t mip_width = max(1u, ici->extent.width >> mip_level);
7161aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis                uint32_t mip_height = max(1u, ici->extent.height >> mip_level);
716279fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis                if ((ivci.subresourceRange.layerCount < pCreateInfo->layers) || (mip_width < pCreateInfo->width) ||
7163aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis                    (mip_height < pCreateInfo->height)) {
71642c911c34092d685a7fa4630028f6fcf4bf80e349Cort Stratton                    skip |= log_msg(
71652c911c34092d685a7fa4630028f6fcf4bf80e349Cort Stratton                        dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
7166315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        VALIDATION_ERROR_094006e4, "DS",
71672c911c34092d685a7fa4630028f6fcf4bf80e349Cort Stratton                        "vkCreateFramebuffer(): VkFramebufferCreateInfo attachment #%u mip level %u has dimensions smaller "
71682c911c34092d685a7fa4630028f6fcf4bf80e349Cort Stratton                        "than the corresponding framebuffer dimensions. Here are the respective dimensions for attachment #%u, "
71692c911c34092d685a7fa4630028f6fcf4bf80e349Cort Stratton                        "framebuffer:\n"
71702c911c34092d685a7fa4630028f6fcf4bf80e349Cort Stratton                        "width: %u, %u\n"
71712c911c34092d685a7fa4630028f6fcf4bf80e349Cort Stratton                        "height: %u, %u\n"
71722c911c34092d685a7fa4630028f6fcf4bf80e349Cort Stratton                        "layerCount: %u, %u\n%s",
71732c911c34092d685a7fa4630028f6fcf4bf80e349Cort Stratton                        i, ivci.subresourceRange.baseMipLevel, i, mip_width, pCreateInfo->width, mip_height, pCreateInfo->height,
7174315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        ivci.subresourceRange.layerCount, pCreateInfo->layers, validation_error_map[VALIDATION_ERROR_094006e4]);
71755ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis                }
717679fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis                if (((ivci.components.r != VK_COMPONENT_SWIZZLE_IDENTITY) && (ivci.components.r != VK_COMPONENT_SWIZZLE_R)) ||
717779fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis                    ((ivci.components.g != VK_COMPONENT_SWIZZLE_IDENTITY) && (ivci.components.g != VK_COMPONENT_SWIZZLE_G)) ||
717879fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis                    ((ivci.components.b != VK_COMPONENT_SWIZZLE_IDENTITY) && (ivci.components.b != VK_COMPONENT_SWIZZLE_B)) ||
717979fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis                    ((ivci.components.a != VK_COMPONENT_SWIZZLE_IDENTITY) && (ivci.components.a != VK_COMPONENT_SWIZZLE_A))) {
71803251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= log_msg(
71815b9ab1fb8720c30edfbe8dd974e2364425471ad5Mark Lobodzinski                        dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
7182315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        VALIDATION_ERROR_094006e8, "DS",
7183da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis                        "vkCreateFramebuffer(): VkFramebufferCreateInfo attachment #%u has non-identy swizzle. All framebuffer "
7184da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis                        "attachments must have been created with the identity swizzle. Here are the actual swizzle values:\n"
7185da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis                        "r swizzle = %s\n"
7186da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis                        "g swizzle = %s\n"
7187da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis                        "b swizzle = %s\n"
71889bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt                        "a swizzle = %s\n"
71899bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt                        "%s",
719079fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis                        i, string_VkComponentSwizzle(ivci.components.r), string_VkComponentSwizzle(ivci.components.g),
71919bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt                        string_VkComponentSwizzle(ivci.components.b), string_VkComponentSwizzle(ivci.components.a),
7192315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_094006e8]);
71935ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis                }
71945ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis            }
7195d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis        }
71965ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis        // Verify correct attachment usage flags
71976600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski        for (uint32_t subpass = 0; subpass < rpci->subpassCount; subpass++) {
71986600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski            // Verify input attachments:
71993251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |=
72009bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt                MatchUsage(dev_data, rpci->pSubpasses[subpass].inputAttachmentCount, rpci->pSubpasses[subpass].pInputAttachments,
7201315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                           pCreateInfo, VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT, VALIDATION_ERROR_094006de);
72026600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski            // Verify color attachments:
72033251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |=
72049bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt                MatchUsage(dev_data, rpci->pSubpasses[subpass].colorAttachmentCount, rpci->pSubpasses[subpass].pColorAttachments,
7205315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                           pCreateInfo, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VALIDATION_ERROR_094006da);
72066600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski            // Verify depth/stencil attachments:
72076600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski            if (rpci->pSubpasses[subpass].pDepthStencilAttachment != nullptr) {
72083251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= MatchUsage(dev_data, 1, rpci->pSubpasses[subpass].pDepthStencilAttachment, pCreateInfo,
7209315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                   VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VALIDATION_ERROR_094006dc);
72106600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski            }
72116600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski        }
72126600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski    }
72136fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis    // Verify FB dimensions are within physical device limits
72149bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt    if (pCreateInfo->width > dev_data->phys_dev_properties.properties.limits.maxFramebufferWidth) {
72153251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
7216315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        VALIDATION_ERROR_094006ec, "DS",
72173251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "vkCreateFramebuffer(): Requested VkFramebufferCreateInfo width exceeds physical device limits. "
72183251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "Requested width: %u, device max: %u\n"
72193251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "%s",
72203251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        pCreateInfo->width, dev_data->phys_dev_properties.properties.limits.maxFramebufferWidth,
7221315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_094006ec]);
72229bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt    }
72239bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt    if (pCreateInfo->height > dev_data->phys_dev_properties.properties.limits.maxFramebufferHeight) {
72243251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
7225315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        VALIDATION_ERROR_094006f0, "DS",
72263251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "vkCreateFramebuffer(): Requested VkFramebufferCreateInfo height exceeds physical device limits. "
72273251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "Requested height: %u, device max: %u\n"
72283251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "%s",
72293251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        pCreateInfo->height, dev_data->phys_dev_properties.properties.limits.maxFramebufferHeight,
7230315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_094006f0]);
72319bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt    }
72329bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt    if (pCreateInfo->layers > dev_data->phys_dev_properties.properties.limits.maxFramebufferLayers) {
72333251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
7234315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        VALIDATION_ERROR_094006f4, "DS",
72353251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "vkCreateFramebuffer(): Requested VkFramebufferCreateInfo layers exceeds physical device limits. "
72363251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "Requested layers: %u, device max: %u\n"
72373251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "%s",
72383251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        pCreateInfo->layers, dev_data->phys_dev_properties.properties.limits.maxFramebufferLayers,
7239315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_094006f4]);
72406fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis    }
7241c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton    // Verify FB dimensions are greater than zero
7242c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton    if (pCreateInfo->width <= 0) {
7243c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
7244315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        VALIDATION_ERROR_094006ea, "DS",
7245c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton                        "vkCreateFramebuffer(): Requested VkFramebufferCreateInfo width must be greater than zero. %s",
7246315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_094006ea]);
7247c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton    }
7248c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton    if (pCreateInfo->height <= 0) {
7249c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
7250315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        VALIDATION_ERROR_094006ee, "DS",
7251c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton                        "vkCreateFramebuffer(): Requested VkFramebufferCreateInfo height must be greater than zero. %s",
7252315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_094006ee]);
7253c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton    }
7254c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton    if (pCreateInfo->layers <= 0) {
7255c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
7256315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        VALIDATION_ERROR_094006f2, "DS",
7257c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton                        "vkCreateFramebuffer(): Requested VkFramebufferCreateInfo layers must be greater than zero. %s",
7258315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_094006f2]);
7259c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton    }
72603251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
72616600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski}
72626600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski
726364c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis// Validate VkFramebufferCreateInfo state prior to calling down chain to create Framebuffer object
726464c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis//  Return true if an error is encountered and callback returns true to skip call down chain
726564c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis//   false indicates that call down chain should proceed
726664c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlisstatic bool PreCallValidateCreateFramebuffer(layer_data *dev_data, const VkFramebufferCreateInfo *pCreateInfo) {
726764c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis    // TODO : Verify that renderPass FB is created with is compatible with FB
72683251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
72693251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    skip |= ValidateFramebufferCreateInfo(dev_data, pCreateInfo);
72703251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
727164c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis}
727264c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis
727354e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis// CreateFramebuffer state has been validated and call down chain completed so record new framebuffer object
727454e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlisstatic void PostCallRecordCreateFramebuffer(layer_data *dev_data, const VkFramebufferCreateInfo *pCreateInfo, VkFramebuffer fb) {
727554e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis    // Shadow create info and store in map
7276c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis    std::unique_ptr<FRAMEBUFFER_STATE> fb_state(
7277c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis        new FRAMEBUFFER_STATE(fb, pCreateInfo, dev_data->renderPassMap[pCreateInfo->renderPass]->createInfo.ptr()));
727876f04ca0e692f9f15d5ef7e0c658c24d11f34ebcTobin Ehlis
727954e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis    for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) {
728054e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis        VkImageView view = pCreateInfo->pAttachments[i];
72819a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto view_state = GetImageViewState(dev_data, view);
728279fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis        if (!view_state) {
728354e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis            continue;
728454e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis        }
728554e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis        MT_FB_ATTACHMENT_INFO fb_info;
7286883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis        fb_info.view_state = view_state;
728779fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis        fb_info.image = view_state->create_info.image;
7288c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis        fb_state->attachments.push_back(fb_info);
728954e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis    }
7290c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis    dev_data->frameBufferMap[fb] = std::move(fb_state);
729154e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis}
729254e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis
729389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateFramebuffer(VkDevice device, const VkFramebufferCreateInfo *pCreateInfo,
7294bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                 const VkAllocationCallbacks *pAllocator, VkFramebuffer *pFramebuffer) {
729556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
7296ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
72973251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = PreCallValidateCreateFramebuffer(dev_data, pCreateInfo);
729864c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis    lock.unlock();
729964c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis
73003251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
730164c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis
73024a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.CreateFramebuffer(device, pCreateInfo, pAllocator, pFramebuffer);
73036600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski
73045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
730564c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis        lock.lock();
730654e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis        PostCallRecordCreateFramebuffer(dev_data, pCreateInfo, *pFramebuffer);
730754e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis        lock.unlock();
73085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
73095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
73105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
73115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
73124e11bb1277f55311686a42000520791e1db1dd7bbungemanstatic bool FindDependency(const uint32_t index, const uint32_t dependent, const std::vector<DAGNode> &subpass_to_node,
7313e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves                           std::unordered_set<uint32_t> &processed_nodes) {
73145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // If we have already checked this node we have not found a dependency path so return false.
7315cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (processed_nodes.count(index)) return false;
73165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    processed_nodes.insert(index);
73175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    const DAGNode &node = subpass_to_node[index];
73185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Look for a dependency path. If one exists return true else recurse on the previous nodes.
73194e11bb1277f55311686a42000520791e1db1dd7bbungeman    if (std::find(node.prev.begin(), node.prev.end(), dependent) == node.prev.end()) {
73205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (auto elem : node.prev) {
7321cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            if (FindDependency(elem, dependent, subpass_to_node, processed_nodes)) return true;
73225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
73235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    } else {
7324e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves        return true;
73255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
7326e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    return false;
73275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
73285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
73294e11bb1277f55311686a42000520791e1db1dd7bbungemanstatic bool CheckDependencyExists(const layer_data *dev_data, const uint32_t subpass,
73303251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                  const std::vector<uint32_t> &dependent_subpasses, const std::vector<DAGNode> &subpass_to_node,
73313251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                  bool &skip) {
7332e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool result = true;
73335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Loop through all subpasses that share the same attachment and make sure a dependency exists
73345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t k = 0; k < dependent_subpasses.size(); ++k) {
7335cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        if (static_cast<uint32_t>(subpass) == dependent_subpasses[k]) continue;
73365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        const DAGNode &node = subpass_to_node[subpass];
73375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // Check for a specified dependency between the two nodes. If one exists we are done.
73385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        auto prev_elem = std::find(node.prev.begin(), node.prev.end(), dependent_subpasses[k]);
73395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        auto next_elem = std::find(node.next.begin(), node.next.end(), dependent_subpasses[k]);
73405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (prev_elem == node.prev.end() && next_elem == node.next.end()) {
73417655cb8b5eb52badee0b011729a05afa36316d69Jan-Harald Fredriksen            // If no dependency exits an implicit dependency still might. If not, throw an error.
73425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            std::unordered_set<uint32_t> processed_nodes;
73437655cb8b5eb52badee0b011729a05afa36316d69Jan-Harald Fredriksen            if (!(FindDependency(subpass, dependent_subpasses[k], subpass_to_node, processed_nodes) ||
7344bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                  FindDependency(dependent_subpasses[k], subpass, subpass_to_node, processed_nodes))) {
73453251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
73463251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS",
73473251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "A dependency between subpasses %d and %d must exist but one is not specified.", subpass,
73483251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                dependent_subpasses[k]);
7349e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves                result = false;
73505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
73515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
73525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
73535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
73545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
73555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
73568860b85a52096f9f9b28616bc37feed505497a54Chris Forbesstatic bool CheckPreserved(const layer_data *dev_data, const VkRenderPassCreateInfo *pCreateInfo, const int index,
73573251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                           const uint32_t attachment, const std::vector<DAGNode> &subpass_to_node, int depth, bool &skip) {
73585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    const DAGNode &node = subpass_to_node[index];
73595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // If this node writes to the attachment return true as next nodes need to preserve the attachment.
73605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[index];
73615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) {
7362cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        if (attachment == subpass.pColorAttachments[j].attachment) return true;
73635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
7364a4ea781e8fff70c9db0bedad7fcb6bba08e35da7Tony Barbour    for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) {
7365a4ea781e8fff70c9db0bedad7fcb6bba08e35da7Tony Barbour        if (attachment == subpass.pInputAttachments[j].attachment) return true;
7366a4ea781e8fff70c9db0bedad7fcb6bba08e35da7Tony Barbour    }
73675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) {
7368cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        if (attachment == subpass.pDepthStencilAttachment->attachment) return true;
73695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
7370e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool result = false;
73715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Loop through previous nodes and see if any of them write to the attachment.
73725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (auto elem : node.prev) {
73733251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        result |= CheckPreserved(dev_data, pCreateInfo, elem, attachment, subpass_to_node, depth + 1, skip);
73745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
73755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // If the attachment was written to by a previous node than this node needs to preserve it.
73765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (result && depth > 0) {
7377e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves        bool has_preserved = false;
73785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t j = 0; j < subpass.preserveAttachmentCount; ++j) {
73795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (subpass.pPreserveAttachments[j] == attachment) {
7380e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves                has_preserved = true;
73815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                break;
73825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
73835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
7384e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves        if (!has_preserved) {
73853251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
73863251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS",
73873251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "Attachment %d is used by a later subpass and must be preserved in subpass %d.", attachment, index);
73885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
73895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
73905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
73915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
73925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
7393cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskitemplate <class T>
7394cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskibool isRangeOverlapping(T offset1, T size1, T offset2, T size2) {
73955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return (((offset1 + size1) > offset2) && ((offset1 + size1) < (offset2 + size2))) ||
73965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis           ((offset1 > offset2) && (offset1 < (offset2 + size2)));
73975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
73985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
73995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisbool isRegionOverlapping(VkImageSubresourceRange range1, VkImageSubresourceRange range2) {
74005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return (isRangeOverlapping(range1.baseMipLevel, range1.levelCount, range2.baseMipLevel, range2.levelCount) &&
74015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            isRangeOverlapping(range1.baseArrayLayer, range1.layerCount, range2.baseArrayLayer, range2.layerCount));
74025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
74035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
7404c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlisstatic bool ValidateDependencies(const layer_data *dev_data, FRAMEBUFFER_STATE const *framebuffer,
7405127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis                                 RENDER_PASS_STATE const *renderPass) {
74063251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
7407fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes    auto const pFramebufferInfo = framebuffer->createInfo.ptr();
7408fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes    auto const pCreateInfo = renderPass->createInfo.ptr();
7409bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski    auto const &subpass_to_node = renderPass->subpassToNode;
74105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    std::vector<std::vector<uint32_t>> output_attachment_to_subpass(pCreateInfo->attachmentCount);
74115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    std::vector<std::vector<uint32_t>> input_attachment_to_subpass(pCreateInfo->attachmentCount);
74125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    std::vector<std::vector<uint32_t>> overlapping_attachments(pCreateInfo->attachmentCount);
74135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Find overlapping attachments
74145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) {
74155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t j = i + 1; j < pCreateInfo->attachmentCount; ++j) {
74165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            VkImageView viewi = pFramebufferInfo->pAttachments[i];
74175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            VkImageView viewj = pFramebufferInfo->pAttachments[j];
74185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (viewi == viewj) {
74195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                overlapping_attachments[i].push_back(j);
74205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                overlapping_attachments[j].push_back(i);
74215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                continue;
74225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
74239a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            auto view_state_i = GetImageViewState(dev_data, viewi);
74249a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            auto view_state_j = GetImageViewState(dev_data, viewj);
742579fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis            if (!view_state_i || !view_state_j) {
74265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                continue;
74275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
742879fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis            auto view_ci_i = view_state_i->create_info;
742979fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis            auto view_ci_j = view_state_j->create_info;
743079fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis            if (view_ci_i.image == view_ci_j.image && isRegionOverlapping(view_ci_i.subresourceRange, view_ci_j.subresourceRange)) {
74315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                overlapping_attachments[i].push_back(j);
74325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                overlapping_attachments[j].push_back(i);
74335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                continue;
74345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
74359a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            auto image_data_i = GetImageState(dev_data, view_ci_i.image);
74369a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            auto image_data_j = GetImageState(dev_data, view_ci_j.image);
74376d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis            if (!image_data_i || !image_data_j) {
74385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                continue;
74395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
7440e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis            if (image_data_i->binding.mem == image_data_j->binding.mem &&
7441e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis                isRangeOverlapping(image_data_i->binding.offset, image_data_i->binding.size, image_data_j->binding.offset,
7442e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis                                   image_data_j->binding.size)) {
74435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                overlapping_attachments[i].push_back(j);
74445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                overlapping_attachments[j].push_back(i);
74455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
74465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
74475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
74485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < overlapping_attachments.size(); ++i) {
74495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        uint32_t attachment = i;
74505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (auto other_attachment : overlapping_attachments[i]) {
74515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (!(pCreateInfo->pAttachments[attachment].flags & VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT)) {
74529b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT,
7453315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                HandleToUint64(framebuffer->framebuffer), __LINE__, VALIDATION_ERROR_12200682, "DS",
74549b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                "Attachment %d aliases attachment %d but doesn't "
74559b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                "set VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT. %s",
7456315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                attachment, other_attachment, validation_error_map[VALIDATION_ERROR_12200682]);
74575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
74585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (!(pCreateInfo->pAttachments[other_attachment].flags & VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT)) {
74599b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT,
7460315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                HandleToUint64(framebuffer->framebuffer), __LINE__, VALIDATION_ERROR_12200682, "DS",
74619b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                "Attachment %d aliases attachment %d but doesn't "
74629b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                "set VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT. %s",
7463315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                other_attachment, attachment, validation_error_map[VALIDATION_ERROR_12200682]);
74645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
74655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
74665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
74675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Find for each attachment the subpasses that use them.
74681c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young    unordered_set<uint32_t> attachmentIndices;
74695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) {
74705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i];
74711c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young        attachmentIndices.clear();
74725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) {
74735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            uint32_t attachment = subpass.pInputAttachments[j].attachment;
7474cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            if (attachment == VK_ATTACHMENT_UNUSED) continue;
74755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            input_attachment_to_subpass[attachment].push_back(i);
74765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            for (auto overlapping_attachment : overlapping_attachments[attachment]) {
74775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                input_attachment_to_subpass[overlapping_attachment].push_back(i);
74785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
74795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
74805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) {
74815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            uint32_t attachment = subpass.pColorAttachments[j].attachment;
7482cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            if (attachment == VK_ATTACHMENT_UNUSED) continue;
74835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            output_attachment_to_subpass[attachment].push_back(i);
74845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            for (auto overlapping_attachment : overlapping_attachments[attachment]) {
74855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                output_attachment_to_subpass[overlapping_attachment].push_back(i);
74865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
74871c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young            attachmentIndices.insert(attachment);
74885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
74895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) {
74905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            uint32_t attachment = subpass.pDepthStencilAttachment->attachment;
74915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            output_attachment_to_subpass[attachment].push_back(i);
74925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            for (auto overlapping_attachment : overlapping_attachments[attachment]) {
74935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                output_attachment_to_subpass[overlapping_attachment].push_back(i);
74945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
74951c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young
74961c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young            if (attachmentIndices.count(attachment)) {
74973251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |=
7498df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
7499df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                            __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS",
75008860b85a52096f9f9b28616bc37feed505497a54Chris Forbes                            "Cannot use same attachment (%u) as both color and depth output in same subpass (%u).", attachment, i);
75011c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young            }
75025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
75035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
75045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // If there is a dependency needed make sure one exists
75055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) {
75065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i];
75075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // If the attachment is an input then all subpasses that output must have a dependency relationship
75085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) {
750993fe72ec8460857bdb3c101095e6eb96d6171341Chris Forbes            uint32_t attachment = subpass.pInputAttachments[j].attachment;
7510cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            if (attachment == VK_ATTACHMENT_UNUSED) continue;
75113251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            CheckDependencyExists(dev_data, i, output_attachment_to_subpass[attachment], subpass_to_node, skip);
75125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
75135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // If the attachment is an output then all subpasses that use the attachment must have a dependency relationship
75145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) {
751593fe72ec8460857bdb3c101095e6eb96d6171341Chris Forbes            uint32_t attachment = subpass.pColorAttachments[j].attachment;
7516cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            if (attachment == VK_ATTACHMENT_UNUSED) continue;
75173251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            CheckDependencyExists(dev_data, i, output_attachment_to_subpass[attachment], subpass_to_node, skip);
75183251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            CheckDependencyExists(dev_data, i, input_attachment_to_subpass[attachment], subpass_to_node, skip);
75195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
75205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) {
75215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            const uint32_t &attachment = subpass.pDepthStencilAttachment->attachment;
75223251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            CheckDependencyExists(dev_data, i, output_attachment_to_subpass[attachment], subpass_to_node, skip);
75233251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            CheckDependencyExists(dev_data, i, input_attachment_to_subpass[attachment], subpass_to_node, skip);
75245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
75255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
75265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Loop through implicit dependencies, if this pass reads make sure the attachment is preserved for all passes after it was
75275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // written.
75285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) {
75295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i];
75305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) {
75313251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            CheckPreserved(dev_data, pCreateInfo, i, subpass.pInputAttachments[j].attachment, subpass_to_node, 0, skip);
75325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
75335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
75343251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
75355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
75365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
753732f68580aa01aab3e923cb52915a1d3dd4e993c5Chris Forbesstatic bool CreatePassDAG(const layer_data *dev_data, const VkRenderPassCreateInfo *pCreateInfo,
7538ea0a13226a513846fe5a7009783c5536b1255a56Tobin Ehlis                          std::vector<DAGNode> &subpass_to_node, std::vector<bool> &has_self_dependency,
7539ea0a13226a513846fe5a7009783c5536b1255a56Tobin Ehlis                          std::vector<int32_t> &subpass_to_dep_index) {
75403251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
75415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) {
75425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        DAGNode &subpass_node = subpass_to_node[i];
75435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        subpass_node.pass = i;
7544ea0a13226a513846fe5a7009783c5536b1255a56Tobin Ehlis        subpass_to_dep_index[i] = -1;  // Default to no dependency and overwrite below as needed
75455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
75465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < pCreateInfo->dependencyCount; ++i) {
75475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        const VkSubpassDependency &dependency = pCreateInfo->pDependencies[i];
754866a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes        if (dependency.srcSubpass == VK_SUBPASS_EXTERNAL || dependency.dstSubpass == VK_SUBPASS_EXTERNAL) {
754966a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes            if (dependency.srcSubpass == dependency.dstSubpass) {
75503251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |=
7551df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
7552df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                            __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS", "The src and dest subpasses cannot both be external.");
755366a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes            }
755466a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes        } else if (dependency.srcSubpass > dependency.dstSubpass) {
75553251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
75563251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS",
7557ea0a13226a513846fe5a7009783c5536b1255a56Tobin Ehlis                            "Dependency graph must be specified such that an earlier pass cannot depend on a later pass.");
75585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else if (dependency.srcSubpass == dependency.dstSubpass) {
75595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            has_self_dependency[dependency.srcSubpass] = true;
75605c6aacf95832467d52b2fde1130b04bef559573aChris Forbes        } else {
75615c6aacf95832467d52b2fde1130b04bef559573aChris Forbes            subpass_to_node[dependency.dstSubpass].prev.push_back(dependency.srcSubpass);
75625c6aacf95832467d52b2fde1130b04bef559573aChris Forbes            subpass_to_node[dependency.srcSubpass].next.push_back(dependency.dstSubpass);
75635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
7564ea0a13226a513846fe5a7009783c5536b1255a56Tobin Ehlis        if (dependency.srcSubpass != VK_SUBPASS_EXTERNAL) {
7565ea0a13226a513846fe5a7009783c5536b1255a56Tobin Ehlis            subpass_to_dep_index[dependency.srcSubpass] = i;
7566ea0a13226a513846fe5a7009783c5536b1255a56Tobin Ehlis        }
75675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
75683251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
75695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
7570918c283ac4f8c604b79abd0c8b5706d2a7352a34Chris Forbes
757189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo *pCreateInfo,
7572bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                  const VkAllocationCallbacks *pAllocator, VkShaderModule *pShaderModule) {
757356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
75747aec8a354c8de254cab09f6da7f24a794525d31eChris Forbes    bool spirv_valid;
7575b1f65702539fd041337fccd493dc6d38dd2a603eChris Forbes
75767aec8a354c8de254cab09f6da7f24a794525d31eChris Forbes    if (PreCallValidateCreateShaderModule(dev_data, pCreateInfo, &spirv_valid))
75777aec8a354c8de254cab09f6da7f24a794525d31eChris Forbes        return VK_ERROR_VALIDATION_FAILED_EXT;
75785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
75794a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult res = dev_data->dispatch_table.CreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
75805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
758159ae0ccadec962d9ca2cce7584fad6c57c1a4458Tobin Ehlis    if (res == VK_SUCCESS) {
7582ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes        lock_guard_t lock(global_lock);
75837aec8a354c8de254cab09f6da7f24a794525d31eChris Forbes        unique_ptr<shader_module> new_shader_module(spirv_valid ? new shader_module(pCreateInfo) : new shader_module());
75847aec8a354c8de254cab09f6da7f24a794525d31eChris Forbes        dev_data->shaderModuleMap[*pShaderModule] = std::move(new_shader_module);
75855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
75865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return res;
75875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
75885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
75894f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinskistatic bool ValidateAttachmentIndex(layer_data *dev_data, uint32_t attachment, uint32_t attachment_count, const char *type) {
75903251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
75914f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski    if (attachment >= attachment_count && attachment != VK_ATTACHMENT_UNUSED) {
75923251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
7593315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        VALIDATION_ERROR_12200684, "DS",
75943251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "CreateRenderPass: %s attachment %d must be less than the total number of attachments %d. %s", type,
7595315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        attachment, attachment_count, validation_error_map[VALIDATION_ERROR_12200684]);
75964f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski    }
75973251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
75984f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski}
75994f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski
7600bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic bool IsPowerOfTwo(unsigned x) { return x && !(x & (x - 1)); }
7601805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes
76024f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinskistatic bool ValidateRenderpassAttachmentUsage(layer_data *dev_data, const VkRenderPassCreateInfo *pCreateInfo) {
76033251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
76044f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski    for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) {
76054f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i];
76064f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        if (subpass.pipelineBindPoint != VK_PIPELINE_BIND_POINT_GRAPHICS) {
76073251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
7608315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            __LINE__, VALIDATION_ERROR_14000698, "DS",
76093251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "CreateRenderPass: Pipeline bind point for subpass %d must be VK_PIPELINE_BIND_POINT_GRAPHICS. %s", i,
7610315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            validation_error_map[VALIDATION_ERROR_14000698]);
76114f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        }
7612ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton
76134f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        for (uint32_t j = 0; j < subpass.preserveAttachmentCount; ++j) {
76144f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski            uint32_t attachment = subpass.pPreserveAttachments[j];
76154f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski            if (attachment == VK_ATTACHMENT_UNUSED) {
76163251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
7617315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                __LINE__, VALIDATION_ERROR_140006aa, "DS",
76183251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "CreateRenderPass:  Preserve attachment (%d) must not be VK_ATTACHMENT_UNUSED. %s", j,
7619315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                validation_error_map[VALIDATION_ERROR_140006aa]);
76204f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski            } else {
76213251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= ValidateAttachmentIndex(dev_data, attachment, pCreateInfo->attachmentCount, "Preserve");
7622ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton
7623ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                bool found = (subpass.pDepthStencilAttachment != NULL && subpass.pDepthStencilAttachment->attachment == attachment);
7624ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                for (uint32_t r = 0; !found && r < subpass.inputAttachmentCount; ++r) {
7625ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                    found = (subpass.pInputAttachments[r].attachment == attachment);
7626ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                }
7627ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                for (uint32_t r = 0; !found && r < subpass.colorAttachmentCount; ++r) {
7628ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                    found = (subpass.pColorAttachments[r].attachment == attachment) ||
7629ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                            (subpass.pResolveAttachments != NULL && subpass.pResolveAttachments[r].attachment == attachment);
7630ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                }
7631ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                if (found) {
7632ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                    skip |= log_msg(
7633ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                        dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
7634315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        VALIDATION_ERROR_140006ac, "DS",
7635ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                        "CreateRenderPass: subpass %u pPreserveAttachments[%u] (%u) must not be used elsewhere in the subpass. %s",
7636315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        i, j, attachment, validation_error_map[VALIDATION_ERROR_140006ac]);
7637ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                }
76384f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski            }
76394f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        }
76406a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes
7641bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        auto subpass_performs_resolve =
7642bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski            subpass.pResolveAttachments &&
7643bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski            std::any_of(subpass.pResolveAttachments, subpass.pResolveAttachments + subpass.colorAttachmentCount,
7644bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                        [](VkAttachmentReference ref) { return ref.attachment != VK_ATTACHMENT_UNUSED; });
76456a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes
7646805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes        unsigned sample_count = 0;
7647805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes
76484f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) {
76494f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski            uint32_t attachment;
76504f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski            if (subpass.pResolveAttachments) {
76514f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski                attachment = subpass.pResolveAttachments[j].attachment;
76523251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= ValidateAttachmentIndex(dev_data, attachment, pCreateInfo->attachmentCount, "Resolve");
76536a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes
76543251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                if (!skip && attachment != VK_ATTACHMENT_UNUSED &&
76556a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes                    pCreateInfo->pAttachments[attachment].samples != VK_SAMPLE_COUNT_1_BIT) {
76563251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT,
7657315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    0, __LINE__, VALIDATION_ERROR_140006a2, "DS",
76583251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    "CreateRenderPass:  Subpass %u requests multisample resolve into attachment %u, "
76593251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    "which must have VK_SAMPLE_COUNT_1_BIT but has %s. %s",
76603251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    i, attachment, string_VkSampleCountFlagBits(pCreateInfo->pAttachments[attachment].samples),
7661315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    validation_error_map[VALIDATION_ERROR_140006a2]);
76626a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes                }
7663ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton
7664ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                if (!skip && subpass.pResolveAttachments[j].attachment != VK_ATTACHMENT_UNUSED &&
7665ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                    subpass.pColorAttachments[j].attachment == VK_ATTACHMENT_UNUSED) {
7666ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                    skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT,
7667315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    0, __LINE__, VALIDATION_ERROR_1400069e, "DS",
7668ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                                    "CreateRenderPass:  Subpass %u requests multisample resolve from attachment %u "
7669ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                                    "which has attachment=VK_ATTACHMENT_UNUSED. %s",
7670315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    i, attachment, validation_error_map[VALIDATION_ERROR_1400069e]);
7671ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                }
76724f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski            }
76734f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski            attachment = subpass.pColorAttachments[j].attachment;
76743251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= ValidateAttachmentIndex(dev_data, attachment, pCreateInfo->attachmentCount, "Color");
76756a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes
76763251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            if (!skip && attachment != VK_ATTACHMENT_UNUSED) {
7677805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes                sample_count |= (unsigned)pCreateInfo->pAttachments[attachment].samples;
7678805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes
7679bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                if (subpass_performs_resolve && pCreateInfo->pAttachments[attachment].samples == VK_SAMPLE_COUNT_1_BIT) {
76803251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT,
7681315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    0, __LINE__, VALIDATION_ERROR_140006a0, "DS",
76823251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    "CreateRenderPass:  Subpass %u requests multisample resolve from attachment %u "
76833251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    "which has VK_SAMPLE_COUNT_1_BIT. %s",
7684315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    i, attachment, validation_error_map[VALIDATION_ERROR_140006a0]);
7685dc7c45f01ae5690f7c969b4760463c1a6bac52d5Chris Forbes                }
7686ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton
7687ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                if (subpass_performs_resolve && subpass.pResolveAttachments[j].attachment != VK_ATTACHMENT_UNUSED) {
7688ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                    const auto &color_desc = pCreateInfo->pAttachments[attachment];
7689ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                    const auto &resolve_desc = pCreateInfo->pAttachments[subpass.pResolveAttachments[j].attachment];
7690ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                    if (color_desc.format != resolve_desc.format) {
7691315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        skip |=
7692315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT,
7693315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    0, __LINE__, VALIDATION_ERROR_140006a4, "DS",
7694315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    "CreateRenderPass:  Subpass %u pColorAttachments[%u] resolves to an attachment with a "
7695315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    "different format. "
7696315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    "color format: %u, resolve format: %u. %s",
7697315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    i, j, color_desc.format, resolve_desc.format, validation_error_map[VALIDATION_ERROR_140006a4]);
7698ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                    }
7699ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                }
77006a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes            }
77014f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        }
7702dc7c45f01ae5690f7c969b4760463c1a6bac52d5Chris Forbes
77034f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) {
77044f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski            uint32_t attachment = subpass.pDepthStencilAttachment->attachment;
77053251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= ValidateAttachmentIndex(dev_data, attachment, pCreateInfo->attachmentCount, "Depth stencil");
7706805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes
77073251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            if (!skip && attachment != VK_ATTACHMENT_UNUSED) {
7708805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes                sample_count |= (unsigned)pCreateInfo->pAttachments[attachment].samples;
7709805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes            }
77104f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        }
7711dc7c45f01ae5690f7c969b4760463c1a6bac52d5Chris Forbes
77124f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) {
77134f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski            uint32_t attachment = subpass.pInputAttachments[j].attachment;
77143251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= ValidateAttachmentIndex(dev_data, attachment, pCreateInfo->attachmentCount, "Input");
77154f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        }
7716805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes
7717805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes        if (sample_count && !IsPowerOfTwo(sample_count)) {
77183251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
7719315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            __LINE__, VALIDATION_ERROR_0082b401, "DS",
77203251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "CreateRenderPass:  Subpass %u attempts to render to "
77213251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "attachments with inconsistent sample counts. %s",
7722315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            i, validation_error_map[VALIDATION_ERROR_0082b401]);
7723805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes        }
77244f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski    }
77253251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
77264f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski}
77274f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski
77285245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbesstatic void MarkAttachmentFirstUse(RENDER_PASS_STATE *render_pass,
77295245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes                                   uint32_t index,
77305245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes                                   bool is_read) {
77315245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes    if (index == VK_ATTACHMENT_UNUSED)
77325245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes        return;
77335245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes
77345245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes    if (!render_pass->attachment_first_read.count(index))
77355245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes        render_pass->attachment_first_read[index] = is_read;
77365245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes}
77375245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes
773889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateRenderPass(VkDevice device, const VkRenderPassCreateInfo *pCreateInfo,
77394f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski                                                const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass) {
77403251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
774156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
77424f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski
7743ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
77444f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski    // TODO: As part of wrapping up the mem_tracker/core_validation merge the following routine should be consolidated with
77454f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski    //       ValidateLayouts.
77463251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    skip |= ValidateRenderpassAttachmentUsage(dev_data, pCreateInfo);
7747208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis    for (uint32_t i = 0; i < pCreateInfo->dependencyCount; ++i) {
77483251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateStageMaskGsTsEnables(dev_data, pCreateInfo->pDependencies[i].srcStageMask, "vkCreateRenderPass()",
7749315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                             VALIDATION_ERROR_13e006b8, VALIDATION_ERROR_13e006bc);
77503251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateStageMaskGsTsEnables(dev_data, pCreateInfo->pDependencies[i].dstStageMask, "vkCreateRenderPass()",
7751315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                             VALIDATION_ERROR_13e006ba, VALIDATION_ERROR_13e006be);
7752208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis    }
77533251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (!skip) {
77543251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateLayouts(dev_data, device, pCreateInfo);
7755ab38df28c5ae1816c5fa33c0c7840c6950e83f0dChris Forbes    }
7756ff6101de02d1677fb54962e2ff57875e76898e26Chris Forbes    lock.unlock();
77574f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski
77583251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (skip) {
77594f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        return VK_ERROR_VALIDATION_FAILED_EXT;
77604f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski    }
77614f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski
77624a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.CreateRenderPass(device, pCreateInfo, pAllocator, pRenderPass);
7763ff6101de02d1677fb54962e2ff57875e76898e26Chris Forbes
77645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
77654f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        lock.lock();
77664f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski
77674f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        std::vector<bool> has_self_dependency(pCreateInfo->subpassCount);
77684f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        std::vector<DAGNode> subpass_to_node(pCreateInfo->subpassCount);
7769ea0a13226a513846fe5a7009783c5536b1255a56Tobin Ehlis        std::vector<int32_t> subpass_to_dep_index(pCreateInfo->subpassCount);
7770ea0a13226a513846fe5a7009783c5536b1255a56Tobin Ehlis        skip |= CreatePassDAG(dev_data, pCreateInfo, subpass_to_node, has_self_dependency, subpass_to_dep_index);
77714f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski
7772127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis        auto render_pass = unique_ptr<RENDER_PASS_STATE>(new RENDER_PASS_STATE(pCreateInfo));
777398cddf7090b5d5dcc382045867753ef703d1c3d3Chris Forbes        render_pass->renderPass = *pRenderPass;
7774cf2686cdbb12af8a29ca598c126b5e37215f0ef7Chris Forbes        render_pass->hasSelfDependency = has_self_dependency;
7775cf2686cdbb12af8a29ca598c126b5e37215f0ef7Chris Forbes        render_pass->subpassToNode = subpass_to_node;
7776ea0a13226a513846fe5a7009783c5536b1255a56Tobin Ehlis        render_pass->subpass_to_dependency_index = subpass_to_dep_index;
7777db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes
777887e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis        for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) {
777987e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis            const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i];
778087e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis            for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) {
77815245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes                MarkAttachmentFirstUse(render_pass.get(), subpass.pColorAttachments[j].attachment, false);
77829cde292b1c19c643b7c13018d9834cccfe6ef7eaChris Forbes
77835245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes                // resolve attachments are considered to be written
77845245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes                if (subpass.pResolveAttachments) {
77855245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes                    MarkAttachmentFirstUse(render_pass.get(), subpass.pResolveAttachments[j].attachment, false);
77869cde292b1c19c643b7c13018d9834cccfe6ef7eaChris Forbes                }
778787e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis            }
77885245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes            if (subpass.pDepthStencilAttachment) {
77895245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes                MarkAttachmentFirstUse(render_pass.get(), subpass.pDepthStencilAttachment->attachment, false);
779087e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis            }
7791a5ce96d7c88653668a2b33a6b72bd3cb16d73f48Michael Lentine            for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) {
77925245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes                MarkAttachmentFirstUse(render_pass.get(), subpass.pInputAttachments[j].attachment, true);
7793a5ce96d7c88653668a2b33a6b72bd3cb16d73f48Michael Lentine            }
779487e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis        }
7795db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes
7796fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes        dev_data->renderPassMap[*pRenderPass] = std::move(render_pass);
77975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
77985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
77995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
78004f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski
7801eb4c61477130f69f48fdf3ac31cb82104181cc73Chris Forbesstatic bool validatePrimaryCommandBuffer(const layer_data *dev_data, const GLOBAL_CB_NODE *pCB, char const *cmd_name,
78029bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt                                         UNIQUE_VALIDATION_ERROR_CODE error_code) {
78033251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
78045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB->createInfo.level != VK_COMMAND_BUFFER_LEVEL_PRIMARY) {
78053251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
78069b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        HandleToUint64(pCB->commandBuffer), __LINE__, error_code, "DS",
78079b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        "Cannot execute command %s on a secondary command buffer. %s", cmd_name, validation_error_map[error_code]);
78085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
78093251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
78105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
78115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
78128860b85a52096f9f9b28616bc37feed505497a54Chris Forbesstatic bool VerifyRenderAreaBounds(const layer_data *dev_data, const VkRenderPassBeginInfo *pRenderPassBegin) {
78133251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
7814c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis    const safe_VkFramebufferCreateInfo *pFramebufferInfo =
78159a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        &GetFramebufferState(dev_data, pRenderPassBegin->framebuffer)->createInfo;
7816885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine    if (pRenderPassBegin->renderArea.offset.x < 0 ||
7817885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine        (pRenderPassBegin->renderArea.offset.x + pRenderPassBegin->renderArea.extent.width) > pFramebufferInfo->width ||
7818885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine        pRenderPassBegin->renderArea.offset.y < 0 ||
7819885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine        (pRenderPassBegin->renderArea.offset.y + pRenderPassBegin->renderArea.extent.height) > pFramebufferInfo->height) {
78203251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= static_cast<bool>(log_msg(
7821df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski            dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
7822885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine            DRAWSTATE_INVALID_RENDER_AREA, "CORE",
7823885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine            "Cannot execute a render pass with renderArea not within the bound of the "
7824885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine            "framebuffer. RenderArea: x %d, y %d, width %d, height %d. Framebuffer: width %d, "
7825885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine            "height %d.",
7826885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine            pRenderPassBegin->renderArea.offset.x, pRenderPassBegin->renderArea.offset.y, pRenderPassBegin->renderArea.extent.width,
7827885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine            pRenderPassBegin->renderArea.extent.height, pFramebufferInfo->width, pFramebufferInfo->height));
7828885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine    }
78293251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
7830885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine}
7831885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine
78321a65650f856376768d7b03ea2d080aaff87cacfdMark 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
78331a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski// [load|store]Op flag must be checked
78341a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski// TODO: The memory valid flag in DEVICE_MEM_INFO should probably be split to track the validity of stencil memory separately.
7835cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskitemplate <typename T>
7836cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskistatic bool FormatSpecificLoadAndStoreOpSettings(VkFormat format, T color_depth_op, T stencil_op, T op) {
7837a49b8a211ce07e7fa2225d23f8cb11f1055b418aMark Lobodzinski    if (color_depth_op != op && stencil_op != op) {
7838a49b8a211ce07e7fa2225d23f8cb11f1055b418aMark Lobodzinski        return false;
7839a49b8a211ce07e7fa2225d23f8cb11f1055b418aMark Lobodzinski    }
784016769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton    bool check_color_depth_load_op = !FormatIsStencilOnly(format);
784116769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton    bool check_stencil_load_op = FormatIsDepthAndStencil(format) || !check_color_depth_load_op;
7842a49b8a211ce07e7fa2225d23f8cb11f1055b418aMark Lobodzinski
78430d9453d85335963d6cabfbf400b058dc905ea238Chris Forbes    return ((check_color_depth_load_op && (color_depth_op == op)) ||
78440d9453d85335963d6cabfbf400b058dc905ea238Chris Forbes            (check_stencil_load_op && (stencil_op == op)));
78451a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski}
78461a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski
7847bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBeginRenderPass(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *pRenderPassBegin,
7848bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                              VkSubpassContents contents) {
78493251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
785056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
7851ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
78529a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *cb_node = GetCBNode(dev_data, commandBuffer);
78539a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto render_pass_state = pRenderPassBegin ? GetRenderPassState(dev_data, pRenderPassBegin->renderPass) : nullptr;
78549a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto framebuffer = pRenderPassBegin ? GetFramebufferState(dev_data, pRenderPassBegin->framebuffer) : nullptr;
7855f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis    if (cb_node) {
7856308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski        if (render_pass_state) {
7857cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            uint32_t clear_op_size = 0;  // Make sure pClearValues is at least as large as last LOAD_OP_CLEAR
7858f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis            cb_node->activeFramebuffer = pRenderPassBegin->framebuffer;
7859308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski            for (uint32_t i = 0; i < render_pass_state->createInfo.attachmentCount; ++i) {
7860f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes                MT_FB_ATTACHMENT_INFO &fb_info = framebuffer->attachments[i];
7861308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski                auto pAttachment = &render_pass_state->createInfo.pAttachments[i];
7862bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                if (FormatSpecificLoadAndStoreOpSettings(pAttachment->format, pAttachment->loadOp, pAttachment->stencilLoadOp,
78631a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski                                                         VK_ATTACHMENT_LOAD_OP_CLEAR)) {
786492bc0680357019834b7529148ab6d73353ce02c7Mark Lobodzinski                    clear_op_size = static_cast<uint32_t>(i) + 1;
786516387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes                    std::function<bool()> function = [=]() {
78669a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                        SetImageMemoryValid(dev_data, GetImageState(dev_data, fb_info.image), true);
786716387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes                        return false;
786816387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes                    };
7869f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis                    cb_node->validate_functions.push_back(function);
7870db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes                } else if (FormatSpecificLoadAndStoreOpSettings(pAttachment->format, pAttachment->loadOp,
7871bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                                pAttachment->stencilLoadOp, VK_ATTACHMENT_LOAD_OP_DONT_CARE)) {
787216387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes                    std::function<bool()> function = [=]() {
78739a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                        SetImageMemoryValid(dev_data, GetImageState(dev_data, fb_info.image), false);
787416387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes                        return false;
787516387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes                    };
7876f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis                    cb_node->validate_functions.push_back(function);
7877db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes                } else if (FormatSpecificLoadAndStoreOpSettings(pAttachment->format, pAttachment->loadOp,
7878bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                                pAttachment->stencilLoadOp, VK_ATTACHMENT_LOAD_OP_LOAD)) {
787916387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes                    std::function<bool()> function = [=]() {
78809a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                        return ValidateImageMemoryIsValid(dev_data, GetImageState(dev_data, fb_info.image),
7881f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis                                                          "vkCmdBeginRenderPass()");
788216387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes                    };
7883f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis                    cb_node->validate_functions.push_back(function);
788416387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes                }
7885308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski                if (render_pass_state->attachment_first_read[i]) {
788616387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes                    std::function<bool()> function = [=]() {
78879a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                        return ValidateImageMemoryIsValid(dev_data, GetImageState(dev_data, fb_info.image),
7888f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis                                                          "vkCmdBeginRenderPass()");
788916387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes                    };
7890f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis                    cb_node->validate_functions.push_back(function);
78915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
78925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
78936de3c6ffa0819ee37cd5cecee918b062145e2ff1Tobin Ehlis            if (clear_op_size > pRenderPassBegin->clearValueCount) {
78943251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(
7895369cf6deef1fca74f9eb1f8ef6e96deba715b133Slawomir Cygan                    dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT,
7896315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                    HandleToUint64(render_pass_state->renderPass), __LINE__, VALIDATION_ERROR_1200070c, "DS",
7897bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                    "In vkCmdBeginRenderPass() the VkRenderPassBeginInfo struct has a clearValueCount of %u but there must "
7898bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                    "be at least %u entries in pClearValues array to account for the highest index attachment in renderPass "
7899cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                    "0x%" PRIx64
7900cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                    " that uses VK_ATTACHMENT_LOAD_OP_CLEAR is %u. Note that the pClearValues array "
7901bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                    "is indexed by attachment number so even if some pClearValues entries between 0 and %u correspond to "
7902bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                    "attachments that aren't cleared they will be ignored. %s",
79039b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                    pRenderPassBegin->clearValueCount, clear_op_size, HandleToUint64(render_pass_state->renderPass), clear_op_size,
7904315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                    clear_op_size - 1, validation_error_map[VALIDATION_ERROR_1200070c]);
7905369cf6deef1fca74f9eb1f8ef6e96deba715b133Slawomir Cygan            }
79063251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= VerifyRenderAreaBounds(dev_data, pRenderPassBegin);
79073251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= VerifyFramebufferAndRenderPassLayouts(dev_data, cb_node, pRenderPassBegin,
79083251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                                          GetFramebufferState(dev_data, pRenderPassBegin->framebuffer));
7909315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis            skip |= insideRenderPass(dev_data, cb_node, "vkCmdBeginRenderPass()", VALIDATION_ERROR_17a00017);
79103251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= ValidateDependencies(dev_data, framebuffer, render_pass_state);
7911315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis            skip |= validatePrimaryCommandBuffer(dev_data, cb_node, "vkCmdBeginRenderPass()", VALIDATION_ERROR_17a00019);
7912315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis            skip |= ValidateCmdQueueFlags(dev_data, cb_node, "vkCmdBeginRenderPass()", VK_QUEUE_GRAPHICS_BIT,
7913315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                          VALIDATION_ERROR_17a02415);
79143251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= ValidateCmd(dev_data, cb_node, CMD_BEGINRENDERPASS, "vkCmdBeginRenderPass()");
7915308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski            cb_node->activeRenderPass = render_pass_state;
79165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            // This is a shallow copy as that is all that is needed for now
7917f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis            cb_node->activeRenderPassBeginInfo = *pRenderPassBegin;
7918f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis            cb_node->activeSubpass = 0;
7919f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis            cb_node->activeSubpassContents = contents;
7920f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis            cb_node->framebuffers.insert(pRenderPassBegin->framebuffer);
7921883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis            // Connect this framebuffer and its children to this cmdBuffer
7922883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis            AddFramebufferBinding(dev_data, cb_node, framebuffer);
79235f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis            // transition attachments to the correct layouts for beginning of renderPass and first subpass
79245f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis            TransitionBeginRenderPassLayouts(dev_data, cb_node, render_pass_state, framebuffer);
79255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
79265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
7927b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
79283251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (!skip) {
79294a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdBeginRenderPass(commandBuffer, pRenderPassBegin, contents);
79305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
79315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
79325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
793389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents) {
79343251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
793556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
7936ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
79379a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer);
79385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
7939315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= validatePrimaryCommandBuffer(dev_data, pCB, "vkCmdNextSubpass()", VALIDATION_ERROR_1b600019);
7940315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdNextSubpass()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_1b602415);
79413251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateCmd(dev_data, pCB, CMD_NEXTSUBPASS, "vkCmdNextSubpass()");
7942315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= outsideRenderPass(dev_data, pCB, "vkCmdNextSubpass()", VALIDATION_ERROR_1b600017);
794380281691386b37385846f21b38e8c9d4b12cc74eChris Forbes
7944fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes        auto subpassCount = pCB->activeRenderPass->createInfo.subpassCount;
794580281691386b37385846f21b38e8c9d4b12cc74eChris Forbes        if (pCB->activeSubpass == subpassCount - 1) {
79463251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
7947315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_1b60071a, "DS",
79483251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "vkCmdNextSubpass(): Attempted to advance beyond final subpass. %s",
7949315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            validation_error_map[VALIDATION_ERROR_1b60071a]);
795080281691386b37385846f21b38e8c9d4b12cc74eChris Forbes        }
79515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
7952b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
795396ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes
79543251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (skip) return;
795596ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes
79564a0754042cf090e131e9e769d8a3633c228625beChris Forbes    dev_data->dispatch_table.CmdNextSubpass(commandBuffer, contents);
795796ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes
795896ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes    if (pCB) {
7959bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        lock.lock();
7960bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        pCB->activeSubpass++;
7961bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        pCB->activeSubpassContents = contents;
79625f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis        TransitionSubpassLayouts(dev_data, pCB, pCB->activeRenderPass, pCB->activeSubpass,
79639a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                                 GetFramebufferState(dev_data, pCB->activeRenderPassBeginInfo.framebuffer));
796496ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes    }
79655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
79665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
796789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdEndRenderPass(VkCommandBuffer commandBuffer) {
79683251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
796956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
7970ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
79719a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto pCB = GetCBNode(dev_data, commandBuffer);
797255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    FRAMEBUFFER_STATE *framebuffer = NULL;
797358c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes    if (pCB) {
7974127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis        RENDER_PASS_STATE *rp_state = pCB->activeRenderPass;
79759a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        framebuffer = GetFramebufferState(dev_data, pCB->activeFramebuffer);
7976127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis        if (rp_state) {
7977127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis            if (pCB->activeSubpass != rp_state->createInfo.subpassCount - 1) {
79783251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
79799b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, HandleToUint64(commandBuffer), __LINE__,
7980315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                VALIDATION_ERROR_1b00071c, "DS", "vkCmdEndRenderPass(): Called before reaching final subpass. %s",
7981315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                validation_error_map[VALIDATION_ERROR_1b00071c]);
798202a3382f28fc7c6ec6018165be88aa6fc4f05c9eChris Forbes            }
798302a3382f28fc7c6ec6018165be88aa6fc4f05c9eChris Forbes
7984127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis            for (size_t i = 0; i < rp_state->createInfo.attachmentCount; ++i) {
7985e3ad4b1284408353cc56a04951c1df1f35a636ceChris Forbes                MT_FB_ATTACHMENT_INFO &fb_info = framebuffer->attachments[i];
7986127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis                auto pAttachment = &rp_state->createInfo.pAttachments[i];
7987bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                if (FormatSpecificLoadAndStoreOpSettings(pAttachment->format, pAttachment->storeOp, pAttachment->stencilStoreOp,
7988bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                         VK_ATTACHMENT_STORE_OP_STORE)) {
798958c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes                    std::function<bool()> function = [=]() {
79909a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                        SetImageMemoryValid(dev_data, GetImageState(dev_data, fb_info.image), true);
799158c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes                        return false;
799258c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes                    };
799358c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes                    pCB->validate_functions.push_back(function);
7994db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes                } else if (FormatSpecificLoadAndStoreOpSettings(pAttachment->format, pAttachment->storeOp,
7995bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                                pAttachment->stencilStoreOp, VK_ATTACHMENT_STORE_OP_DONT_CARE)) {
799658c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes                    std::function<bool()> function = [=]() {
79979a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                        SetImageMemoryValid(dev_data, GetImageState(dev_data, fb_info.image), false);
799858c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes                        return false;
799958c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes                    };
800058c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes                    pCB->validate_functions.push_back(function);
80015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
80025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
80035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
8004315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= outsideRenderPass(dev_data, pCB, "vkCmdEndRenderpass()", VALIDATION_ERROR_1b000017);
8005315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= validatePrimaryCommandBuffer(dev_data, pCB, "vkCmdEndRenderPass()", VALIDATION_ERROR_1b000019);
8006315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdEndRenderPass()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_1b002415);
80073251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateCmd(dev_data, pCB, CMD_ENDRENDERPASS, "vkCmdEndRenderPass()");
80080e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes    }
80090e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes    lock.unlock();
80100e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes
80113251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (skip) return;
80120e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes
80134a0754042cf090e131e9e769d8a3633c228625beChris Forbes    dev_data->dispatch_table.CmdEndRenderPass(commandBuffer);
80140e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes
80150e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes    if (pCB) {
80160e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes        lock.lock();
801755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        TransitionFinalSubpassLayouts(dev_data, pCB, &pCB->activeRenderPassBeginInfo, framebuffer);
801858c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes        pCB->activeRenderPass = nullptr;
801958c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes        pCB->activeSubpass = 0;
802058c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes        pCB->activeFramebuffer = VK_NULL_HANDLE;
80215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
80225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
80235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
8024a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlisstatic bool logInvalidAttachmentMessage(layer_data *dev_data, VkCommandBuffer secondaryBuffer, uint32_t primaryAttach,
8025a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                                        uint32_t secondaryAttach, const char *msg) {
8026df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski    return log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
8027315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                   HandleToUint64(secondaryBuffer), __LINE__, VALIDATION_ERROR_1b2000c4, "DS",
8028df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                   "vkCmdExecuteCommands() called w/ invalid Secondary Cmd Buffer 0x%" PRIx64
8029df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                   " which has a render pass "
8030df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                   "that is not compatible with the Primary Cmd Buffer current render pass. "
8031df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                   "Attachment %u is not compatible with %u: %s. %s",
80329b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                   HandleToUint64(secondaryBuffer), primaryAttach, secondaryAttach, msg,
8033315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                   validation_error_map[VALIDATION_ERROR_1b2000c4]);
80345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
80355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
8036a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlisstatic bool validateAttachmentCompatibility(layer_data *dev_data, VkCommandBuffer primaryBuffer,
8037a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                                            VkRenderPassCreateInfo const *primaryPassCI, uint32_t primaryAttach,
8038a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                                            VkCommandBuffer secondaryBuffer, VkRenderPassCreateInfo const *secondaryPassCI,
8039e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves                                            uint32_t secondaryAttach, bool is_multi) {
80403251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
8041a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis    if (primaryPassCI->attachmentCount <= primaryAttach) {
80425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        primaryAttach = VK_ATTACHMENT_UNUSED;
80435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
8044a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis    if (secondaryPassCI->attachmentCount <= secondaryAttach) {
80455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        secondaryAttach = VK_ATTACHMENT_UNUSED;
80465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
80475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (primaryAttach == VK_ATTACHMENT_UNUSED && secondaryAttach == VK_ATTACHMENT_UNUSED) {
80483251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        return skip;
80495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
80505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (primaryAttach == VK_ATTACHMENT_UNUSED) {
80513251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= logInvalidAttachmentMessage(dev_data, secondaryBuffer, primaryAttach, secondaryAttach,
80523251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                            "The first is unused while the second is not.");
80533251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        return skip;
80545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
80555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (secondaryAttach == VK_ATTACHMENT_UNUSED) {
80563251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= logInvalidAttachmentMessage(dev_data, secondaryBuffer, primaryAttach, secondaryAttach,
80573251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                            "The second is unused while the first is not.");
80583251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        return skip;
80595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
8060a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis    if (primaryPassCI->pAttachments[primaryAttach].format != secondaryPassCI->pAttachments[secondaryAttach].format) {
80613251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |=
8062a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis            logInvalidAttachmentMessage(dev_data, secondaryBuffer, primaryAttach, secondaryAttach, "They have different formats.");
80635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
8064a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis    if (primaryPassCI->pAttachments[primaryAttach].samples != secondaryPassCI->pAttachments[secondaryAttach].samples) {
80653251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |=
8066a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis            logInvalidAttachmentMessage(dev_data, secondaryBuffer, primaryAttach, secondaryAttach, "They have different samples.");
80675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
8068a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis    if (is_multi && primaryPassCI->pAttachments[primaryAttach].flags != secondaryPassCI->pAttachments[secondaryAttach].flags) {
80693251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |=
8070a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis            logInvalidAttachmentMessage(dev_data, secondaryBuffer, primaryAttach, secondaryAttach, "They have different flags.");
80715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
80723251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
80735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
80745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
8075a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlisstatic bool validateSubpassCompatibility(layer_data *dev_data, VkCommandBuffer primaryBuffer,
8076a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                                         VkRenderPassCreateInfo const *primaryPassCI, VkCommandBuffer secondaryBuffer,
8077a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                                         VkRenderPassCreateInfo const *secondaryPassCI, const int subpass, bool is_multi) {
80783251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
8079a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis    const VkSubpassDescription &primary_desc = primaryPassCI->pSubpasses[subpass];
8080a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis    const VkSubpassDescription &secondary_desc = secondaryPassCI->pSubpasses[subpass];
80815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    uint32_t maxInputAttachmentCount = std::max(primary_desc.inputAttachmentCount, secondary_desc.inputAttachmentCount);
80825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < maxInputAttachmentCount; ++i) {
80835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        uint32_t primary_input_attach = VK_ATTACHMENT_UNUSED, secondary_input_attach = VK_ATTACHMENT_UNUSED;
80845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (i < primary_desc.inputAttachmentCount) {
80855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            primary_input_attach = primary_desc.pInputAttachments[i].attachment;
80865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
80875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (i < secondary_desc.inputAttachmentCount) {
80885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            secondary_input_attach = secondary_desc.pInputAttachments[i].attachment;
80895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
80903251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= validateAttachmentCompatibility(dev_data, primaryBuffer, primaryPassCI, primary_input_attach, secondaryBuffer,
80913251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                                secondaryPassCI, secondary_input_attach, is_multi);
80925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
80935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    uint32_t maxColorAttachmentCount = std::max(primary_desc.colorAttachmentCount, secondary_desc.colorAttachmentCount);
80945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < maxColorAttachmentCount; ++i) {
80955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        uint32_t primary_color_attach = VK_ATTACHMENT_UNUSED, secondary_color_attach = VK_ATTACHMENT_UNUSED;
80965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (i < primary_desc.colorAttachmentCount) {
80975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            primary_color_attach = primary_desc.pColorAttachments[i].attachment;
80985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
80995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (i < secondary_desc.colorAttachmentCount) {
81005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            secondary_color_attach = secondary_desc.pColorAttachments[i].attachment;
81015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
81023251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= validateAttachmentCompatibility(dev_data, primaryBuffer, primaryPassCI, primary_color_attach, secondaryBuffer,
81033251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                                secondaryPassCI, secondary_color_attach, is_multi);
81045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        uint32_t primary_resolve_attach = VK_ATTACHMENT_UNUSED, secondary_resolve_attach = VK_ATTACHMENT_UNUSED;
81055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (i < primary_desc.colorAttachmentCount && primary_desc.pResolveAttachments) {
81065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            primary_resolve_attach = primary_desc.pResolveAttachments[i].attachment;
81075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
81085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (i < secondary_desc.colorAttachmentCount && secondary_desc.pResolveAttachments) {
81095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            secondary_resolve_attach = secondary_desc.pResolveAttachments[i].attachment;
81105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
81113251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= validateAttachmentCompatibility(dev_data, primaryBuffer, primaryPassCI, primary_resolve_attach, secondaryBuffer,
81123251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                                secondaryPassCI, secondary_resolve_attach, is_multi);
81135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
81145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    uint32_t primary_depthstencil_attach = VK_ATTACHMENT_UNUSED, secondary_depthstencil_attach = VK_ATTACHMENT_UNUSED;
81155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (primary_desc.pDepthStencilAttachment) {
81165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        primary_depthstencil_attach = primary_desc.pDepthStencilAttachment[0].attachment;
81175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
81185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (secondary_desc.pDepthStencilAttachment) {
81195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        secondary_depthstencil_attach = secondary_desc.pDepthStencilAttachment[0].attachment;
81205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
81213251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    skip |= validateAttachmentCompatibility(dev_data, primaryBuffer, primaryPassCI, primary_depthstencil_attach, secondaryBuffer,
81223251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                            secondaryPassCI, secondary_depthstencil_attach, is_multi);
81233251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
81245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
81255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
8126a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis// Verify that given renderPass CreateInfo for primary and secondary command buffers are compatible.
8127a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis//  This function deals directly with the CreateInfo, there are overloaded versions below that can take the renderPass handle and
8128a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis//  will then feed into this function
8129a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlisstatic bool validateRenderPassCompatibility(layer_data *dev_data, VkCommandBuffer primaryBuffer,
8130a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                                            VkRenderPassCreateInfo const *primaryPassCI, VkCommandBuffer secondaryBuffer,
8131a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                                            VkRenderPassCreateInfo const *secondaryPassCI) {
81323251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
8133a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis
8134a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis    if (primaryPassCI->subpassCount != secondaryPassCI->subpassCount) {
81353251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
81369b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        HandleToUint64(primaryBuffer), __LINE__, DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS",
81373251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "vkCmdExecuteCommands() called w/ invalid secondary Cmd Buffer 0x%" PRIx64
81383251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        " that has a subpassCount of %u that is incompatible with the primary Cmd Buffer 0x%" PRIx64
81393251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        " that has a subpassCount of %u.",
81409b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        HandleToUint64(secondaryBuffer), secondaryPassCI->subpassCount, HandleToUint64(primaryBuffer),
81419b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        primaryPassCI->subpassCount);
8142a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis    } else {
8143a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis        for (uint32_t i = 0; i < primaryPassCI->subpassCount; ++i) {
81443251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= validateSubpassCompatibility(dev_data, primaryBuffer, primaryPassCI, secondaryBuffer, secondaryPassCI, i,
81453251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                                 primaryPassCI->subpassCount > 1);
8146a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis        }
81475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
81483251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
81495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
81505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
8151e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool validateFramebuffer(layer_data *dev_data, VkCommandBuffer primaryBuffer, const GLOBAL_CB_NODE *pCB,
8152e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves                                VkCommandBuffer secondaryBuffer, const GLOBAL_CB_NODE *pSubCB) {
81533251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
81545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (!pSubCB->beginInfo.pInheritanceInfo) {
81553251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        return skip;
81565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
8157c5b97dda856ff837638b3ebb7e231d5507c495a3Chris Forbes    VkFramebuffer primary_fb = pCB->activeFramebuffer;
81585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    VkFramebuffer secondary_fb = pSubCB->beginInfo.pInheritanceInfo->framebuffer;
81595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (secondary_fb != VK_NULL_HANDLE) {
81605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (primary_fb != secondary_fb) {
81613251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
8162315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(primaryBuffer), __LINE__, VALIDATION_ERROR_1b2000c6, "DS",
81633251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "vkCmdExecuteCommands() called w/ invalid secondary command buffer 0x%" PRIx64
81643251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            " which has a framebuffer 0x%" PRIx64
81653251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            " that is not the same as the primary command buffer's current active framebuffer 0x%" PRIx64 ". %s",
81669b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(secondaryBuffer), HandleToUint64(secondary_fb), HandleToUint64(primary_fb),
8167315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            validation_error_map[VALIDATION_ERROR_1b2000c6]);
81685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
81699a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto fb = GetFramebufferState(dev_data, secondary_fb);
8170e3ad4b1284408353cc56a04951c1df1f35a636ceChris Forbes        if (!fb) {
81713251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
81729b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(primaryBuffer), __LINE__, DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS",
81733251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "vkCmdExecuteCommands() called w/ invalid Cmd Buffer 0x%p "
81743251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "which has invalid framebuffer 0x%" PRIx64 ".",
81759b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            (void *)secondaryBuffer, HandleToUint64(secondary_fb));
81763251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            return skip;
81775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
81789a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto cb_renderpass = GetRenderPassState(dev_data, pSubCB->beginInfo.pInheritanceInfo->renderPass);
8179a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis        if (cb_renderpass->renderPass != fb->createInfo.renderPass) {
81803251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= validateRenderPassCompatibility(dev_data, secondaryBuffer, fb->renderPassCreateInfo.ptr(), secondaryBuffer,
81813251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                                    cb_renderpass->createInfo.ptr());
8182a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis        }
81835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
81843251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
81855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
81865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
8187e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool validateSecondaryCommandBufferState(layer_data *dev_data, GLOBAL_CB_NODE *pCB, GLOBAL_CB_NODE *pSubCB) {
81883251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
81895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    unordered_set<int> activeTypes;
81905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (auto queryObject : pCB->activeQueries) {
81915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        auto queryPoolData = dev_data->queryPoolMap.find(queryObject.pool);
81925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (queryPoolData != dev_data->queryPoolMap.end()) {
81935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (queryPoolData->second.createInfo.queryType == VK_QUERY_TYPE_PIPELINE_STATISTICS &&
81945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                pSubCB->beginInfo.pInheritanceInfo) {
81955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                VkQueryPipelineStatisticFlags cmdBufStatistics = pSubCB->beginInfo.pInheritanceInfo->pipelineStatistics;
81965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                if ((cmdBufStatistics & queryPoolData->second.createInfo.pipelineStatistics) != cmdBufStatistics) {
81979b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                    skip |= log_msg(
81989b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
8199315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(pCB->commandBuffer), __LINE__, VALIDATION_ERROR_1b2000d0, "DS",
82009b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        "vkCmdExecuteCommands() called w/ invalid Cmd Buffer 0x%p "
82019b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        "which has invalid active query pool 0x%" PRIx64
82029b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        ". Pipeline statistics is being queried so the command "
82039b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        "buffer must have all bits set on the queryPool. %s",
8204315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        pCB->commandBuffer, HandleToUint64(queryPoolData->first), validation_error_map[VALIDATION_ERROR_1b2000d0]);
82055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
82065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
82075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            activeTypes.insert(queryPoolData->second.createInfo.queryType);
82085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
82095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
82105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (auto queryObject : pSubCB->startedQueries) {
82115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        auto queryPoolData = dev_data->queryPoolMap.find(queryObject.pool);
82125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (queryPoolData != dev_data->queryPoolMap.end() && activeTypes.count(queryPoolData->second.createInfo.queryType)) {
82139b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
82149b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS",
82159b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            "vkCmdExecuteCommands() called w/ invalid Cmd Buffer 0x%p "
82169b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            "which has invalid active query pool 0x%" PRIx64
82179b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            "of type %d but a query of that type has been started on "
82189b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            "secondary Cmd Buffer 0x%p.",
82199b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            pCB->commandBuffer, HandleToUint64(queryPoolData->first), queryPoolData->second.createInfo.queryType,
82209b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            pSubCB->commandBuffer);
82215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
82225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
82237bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski
82249a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto primary_pool = GetCommandPoolNode(dev_data, pCB->createInfo.commandPool);
82259a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto secondary_pool = GetCommandPoolNode(dev_data, pSubCB->createInfo.commandPool);
82267bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski    if (primary_pool && secondary_pool && (primary_pool->queueFamilyIndex != secondary_pool->queueFamilyIndex)) {
82273251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |=
8228226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis            log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
82299b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                    HandleToUint64(pSubCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_QUEUE_FAMILY, "DS",
8230226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis                    "vkCmdExecuteCommands(): Primary command buffer 0x%p"
8231226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis                    " created in queue family %d has secondary command buffer 0x%p created in queue family %d.",
8232226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis                    pCB->commandBuffer, primary_pool->queueFamilyIndex, pSubCB->commandBuffer, secondary_pool->queueFamilyIndex);
82337bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski    }
82347bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski
82353251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
82365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
82375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
8238bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t commandBuffersCount,
8239bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                              const VkCommandBuffer *pCommandBuffers) {
82403251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
824156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
8242ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
82439a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer);
82445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
82455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        GLOBAL_CB_NODE *pSubCB = NULL;
82465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t i = 0; i < commandBuffersCount; i++) {
82479a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            pSubCB = GetCBNode(dev_data, pCommandBuffers[i]);
82480a8b955c23012196339f3c10ffedc631ea0f7c58Tobin Ehlis            assert(pSubCB);
82490a8b955c23012196339f3c10ffedc631ea0f7c58Tobin Ehlis            if (VK_COMMAND_BUFFER_LEVEL_PRIMARY == pSubCB->createInfo.level) {
82503251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |=
8251df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
8252315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(pCommandBuffers[i]), __LINE__, VALIDATION_ERROR_1b2000b0, "DS",
8253df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                            "vkCmdExecuteCommands() called w/ Primary Cmd Buffer 0x%p in element %u of pCommandBuffers "
8254df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                            "array. All cmd buffers in pCommandBuffers array must be secondary. %s",
8255315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            pCommandBuffers[i], i, validation_error_map[VALIDATION_ERROR_1b2000b0]);
8256cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            } else if (pCB->activeRenderPass) {  // Secondary CB w/i RenderPass must have *CONTINUE_BIT set
82570de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                if (pSubCB->beginInfo.pInheritanceInfo != nullptr) {
82580de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                    auto secondary_rp_state = GetRenderPassState(dev_data, pSubCB->beginInfo.pInheritanceInfo->renderPass);
82590de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                    if (!(pSubCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT)) {
82600de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                        skip |= log_msg(
82610de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                            dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
8262315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(pCommandBuffers[i]), __LINE__, VALIDATION_ERROR_1b2000c0, "DS",
82630de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                            "vkCmdExecuteCommands(): Secondary Command Buffer (0x%p) executed within render pass (0x%" PRIxLEAST64
82640de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                            ") must have had vkBeginCommandBuffer() called w/ VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT "
82650de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                            "set. %s",
82660de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                            pCommandBuffers[i], HandleToUint64(pCB->activeRenderPass->renderPass),
8267315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            validation_error_map[VALIDATION_ERROR_1b2000c0]);
82680de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                    } else {
82690de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                        // Make sure render pass is compatible with parent command buffer pass if has continue
82700de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                        if (pCB->activeRenderPass->renderPass != secondary_rp_state->renderPass) {
82710de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                            skip |=
82720de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                                validateRenderPassCompatibility(dev_data, commandBuffer, pCB->activeRenderPass->createInfo.ptr(),
82733251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                                                pCommandBuffers[i], secondary_rp_state->createInfo.ptr());
82740de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                        }
82750de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                        //  If framebuffer for secondary CB is not NULL, then it must match active FB from primaryCB
82760de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                        skip |= validateFramebuffer(dev_data, commandBuffer, pCB, pCommandBuffers[i], pSubCB);
8277f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                        if (VK_NULL_HANDLE == pSubCB->activeFramebuffer) {
827879fc00370d55e7cbfd4052b579120e64b0a1a4beTobin Ehlis                            //  Inherit primary's activeFramebuffer and while running validate functions
827979fc00370d55e7cbfd4052b579120e64b0a1a4beTobin Ehlis                            for (auto &function : pSubCB->cmd_execute_commands_functions) {
828079fc00370d55e7cbfd4052b579120e64b0a1a4beTobin Ehlis                                skip |= function(pCB->activeFramebuffer);
8281f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                            }
8282f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                        }
82830de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                    }
82840de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                    string errorString = "";
82850de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                    // secondaryCB must have been created w/ RP compatible w/ primaryCB active renderpass
82860de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                    if ((pCB->activeRenderPass->renderPass != secondary_rp_state->renderPass) &&
82870de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                        !verify_renderpass_compatibility(dev_data, pCB->activeRenderPass->createInfo.ptr(),
82880de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                                                         secondary_rp_state->createInfo.ptr(), errorString)) {
82890de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                        skip |= log_msg(
82900de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                            dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
82910de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                            HandleToUint64(pCommandBuffers[i]), __LINE__, DRAWSTATE_RENDERPASS_INCOMPATIBLE, "DS",
82920de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                            "vkCmdExecuteCommands(): Secondary Command Buffer (0x%p) w/ render pass (0x%" PRIxLEAST64
82930de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                            ") is incompatible w/ primary command buffer (0x%p) w/ render pass (0x%" PRIxLEAST64 ") due to: %s",
82940de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                            pCommandBuffers[i], HandleToUint64(pSubCB->beginInfo.pInheritanceInfo->renderPass), commandBuffer,
82950de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                            HandleToUint64(pCB->activeRenderPass->renderPass), errorString.c_str());
8296a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis                    }
82975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
82985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
82995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            // TODO(mlentine): Move more logic into this method
83003251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= validateSecondaryCommandBufferState(dev_data, pCB, pSubCB);
8301315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis            skip |= validateCommandBufferState(dev_data, pSubCB, "vkCmdExecuteCommands()", 0, VALIDATION_ERROR_1b2000b2);
83025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (!(pSubCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT)) {
83039b2582dc67737351a72fbeb82e9e6e8cdff7a026Chris Forbes                if (pSubCB->in_use.load() || pCB->linkedCommandBuffers.count(pSubCB)) {
83043251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
83059b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                    VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, HandleToUint64(pCB->commandBuffer), __LINE__,
8306315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    VALIDATION_ERROR_1b2000b4, "DS",
83073251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    "Attempt to simultaneously execute command buffer 0x%p"
83083251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    " without VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT set! %s",
8309315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    pCB->commandBuffer, validation_error_map[VALIDATION_ERROR_1b2000b4]);
83105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
83115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                if (pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT) {
83125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    // Warn that non-simultaneous secondary cmd buffer renders primary non-simultaneous
83133251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= log_msg(
83145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
83159b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        HandleToUint64(pCommandBuffers[i]), __LINE__, DRAWSTATE_INVALID_CB_SIMULTANEOUS_USE, "DS",
8316226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis                        "vkCmdExecuteCommands(): Secondary Command Buffer (0x%p) "
8317226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis                        "does not have VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT set and will cause primary command buffer "
8318226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis                        "(0x%p) to be treated as if it does not have VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT "
831983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                        "set, even though it does.",
8320226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis                        pCommandBuffers[i], pCB->commandBuffer);
83215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    pCB->beginInfo.flags &= ~VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
83225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
83235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
8324f71dd305f197826a61f398bff725267a20ea1d90Chris Forbes            if (!pCB->activeQueries.empty() && !dev_data->enabled_features.inheritedQueries) {
83253251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |=
8326cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
8327315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(pCommandBuffers[i]), __LINE__, VALIDATION_ERROR_1b2000ca, "DS",
8328cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                            "vkCmdExecuteCommands(): Secondary Command Buffer "
8329cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                            "(0x%p) cannot be submitted with a query in "
8330cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                            "flight and inherited queries not "
8331cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                            "supported on this device. %s",
8332315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            pCommandBuffers[i], validation_error_map[VALIDATION_ERROR_1b2000ca]);
83335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
83349b2582dc67737351a72fbeb82e9e6e8cdff7a026Chris Forbes            // TODO: separate validate from update! This is very tangled.
83358567fecbf563420f5900ade277ca68908aa87259Tobin Ehlis            // Propagate layout transitions to the primary cmd buffer
83368567fecbf563420f5900ade277ca68908aa87259Tobin Ehlis            for (auto ilm_entry : pSubCB->imageLayoutMap) {
833755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski                SetLayout(dev_data, pCB, ilm_entry.first, ilm_entry.second);
83388567fecbf563420f5900ade277ca68908aa87259Tobin Ehlis            }
83395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            pSubCB->primaryCommandBuffer = pCB->commandBuffer;
83401a3660584634742a3297915c94768d73f360e794Chris Forbes            pCB->linkedCommandBuffers.insert(pSubCB);
83411a3660584634742a3297915c94768d73f360e794Chris Forbes            pSubCB->linkedCommandBuffers.insert(pCB);
8342d4ee9fdb2def1e9dc70c5627c9103e264471b8ebMichael Lentine            for (auto &function : pSubCB->queryUpdates) {
8343d4ee9fdb2def1e9dc70c5627c9103e264471b8ebMichael Lentine                pCB->queryUpdates.push_back(function);
8344d4ee9fdb2def1e9dc70c5627c9103e264471b8ebMichael Lentine            }
83455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
8346315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= validatePrimaryCommandBuffer(dev_data, pCB, "vkCmdExecuteCommands()", VALIDATION_ERROR_1b200019);
8347315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |=
8348315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis            ValidateCmdQueueFlags(dev_data, pCB, "vkCmdExecuteCommands()",
8349315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                  VK_QUEUE_TRANSFER_BIT | VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, VALIDATION_ERROR_1b202415);
8350f5a52627a6576d3d532cd1f2e1be6d9987aeda7fChris Forbes        skip |= ValidateCmd(dev_data, pCB, CMD_EXECUTECOMMANDS, "vkCmdExecuteCommands()");
83515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
8352b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
83533251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (!skip) dev_data->dispatch_table.CmdExecuteCommands(commandBuffer, commandBuffersCount, pCommandBuffers);
83545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
83555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
8356bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL MapMemory(VkDevice device, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size, VkFlags flags,
8357bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                         void **ppData) {
835856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
83595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
83603251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
83615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
8362ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
83639a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    DEVICE_MEM_INFO *mem_info = GetMemObjInfo(dev_data, mem);
8364cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis    if (mem_info) {
8365f541bf53dee6daf82a4c8304354eac599a884d29Tobin Ehlis        // TODO : This could me more fine-grained to track just region that is valid
8366f541bf53dee6daf82a4c8304354eac599a884d29Tobin Ehlis        mem_info->global_valid = true;
8367623548a271287ae55415e45e3c654ee66d4e79ffTobin Ehlis        auto end_offset = (VK_WHOLE_SIZE == size) ? mem_info->alloc_info.allocationSize - 1 : offset + size - 1;
83683251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateMapImageLayouts(dev_data, device, mem_info, offset, end_offset);
8369cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis        // TODO : Do we need to create new "bound_range" for the mapped range?
8370623548a271287ae55415e45e3c654ee66d4e79ffTobin Ehlis        SetMemRangesValid(dev_data, mem_info, offset, end_offset);
8371cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis        if ((dev_data->phys_dev_mem_props.memoryTypes[mem_info->alloc_info.memoryTypeIndex].propertyFlags &
8372b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis             VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0) {
83733251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
8374315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                           HandleToUint64(mem), __LINE__, VALIDATION_ERROR_31200554, "MEM",
83753251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                           "Mapping Memory without VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT set: mem obj 0x%" PRIxLEAST64 ". %s",
8376315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                           HandleToUint64(mem), validation_error_map[VALIDATION_ERROR_31200554]);
83775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
83785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
83793251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    skip |= ValidateMapMemRange(dev_data, mem, offset, size);
8380b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
83815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
83823251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (!skip) {
83834a0754042cf090e131e9e769d8a3633c228625beChris Forbes        result = dev_data->dispatch_table.MapMemory(device, mem, offset, size, flags, ppData);
83847c0012acb5327961b0a5191434a08e5fa788786dTobin Ehlis        if (VK_SUCCESS == result) {
83857c0012acb5327961b0a5191434a08e5fa788786dTobin Ehlis            lock.lock();
8386cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis            // TODO : What's the point of this range? See comment on creating new "bound_range" above, which may replace this
83877c0012acb5327961b0a5191434a08e5fa788786dTobin Ehlis            storeMemRanges(dev_data, mem, offset, size);
83885f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            initializeAndTrackMemory(dev_data, mem, offset, size, ppData);
83897c0012acb5327961b0a5191434a08e5fa788786dTobin Ehlis            lock.unlock();
83907c0012acb5327961b0a5191434a08e5fa788786dTobin Ehlis        }
83915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
83925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
83935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
83945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
839589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL UnmapMemory(VkDevice device, VkDeviceMemory mem) {
839656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
83973251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
83985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
8399ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
84003251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    skip |= deleteMemRanges(dev_data, mem);
8401b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
84023251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (!skip) {
84034a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.UnmapMemory(device, mem);
84045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
84055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
84065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
84078860b85a52096f9f9b28616bc37feed505497a54Chris Forbesstatic bool validateMemoryIsMapped(layer_data *dev_data, const char *funcName, uint32_t memRangeCount,
8408e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves                                   const VkMappedMemoryRange *pMemRanges) {
8409c7ee6f2fe100c1aacfaa0872832717c906bb8a4aMark Lobodzinski    bool skip = false;
84105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < memRangeCount; ++i) {
84119a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto mem_info = GetMemObjInfo(dev_data, pMemRanges[i].memory);
841257fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis        if (mem_info) {
8413f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski            if (pMemRanges[i].size == VK_WHOLE_SIZE) {
8414f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski                if (mem_info->mem_range.offset > pMemRanges[i].offset) {
8415315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                    skip |=
8416315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
8417315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                HandleToUint64(pMemRanges[i].memory), __LINE__, VALIDATION_ERROR_0c20055c, "MEM",
8418315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                "%s: Flush/Invalidate offset (" PRINTF_SIZE_T_SPECIFIER
8419315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                ") is less than Memory Object's offset "
8420315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                "(" PRINTF_SIZE_T_SPECIFIER "). %s",
8421315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                funcName, static_cast<size_t>(pMemRanges[i].offset),
8422315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                static_cast<size_t>(mem_info->mem_range.offset), validation_error_map[VALIDATION_ERROR_0c20055c]);
8423f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski                }
8424f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski            } else {
8425f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski                const uint64_t data_end = (mem_info->mem_range.size == VK_WHOLE_SIZE)
8426f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski                                              ? mem_info->alloc_info.allocationSize
8427f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski                                              : (mem_info->mem_range.offset + mem_info->mem_range.size);
8428f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski                if ((mem_info->mem_range.offset > pMemRanges[i].offset) ||
8429f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski                    (data_end < (pMemRanges[i].offset + pMemRanges[i].size))) {
8430c7ee6f2fe100c1aacfaa0872832717c906bb8a4aMark Lobodzinski                    skip |=
8431f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski                        log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
8432315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                HandleToUint64(pMemRanges[i].memory), __LINE__, VALIDATION_ERROR_0c20055a, "MEM",
8433f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski                                "%s: Flush/Invalidate size or offset (" PRINTF_SIZE_T_SPECIFIER ", " PRINTF_SIZE_T_SPECIFIER
8434f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski                                ") exceed the Memory Object's upper-bound "
8435f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski                                "(" PRINTF_SIZE_T_SPECIFIER "). %s",
8436f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski                                funcName, static_cast<size_t>(pMemRanges[i].offset + pMemRanges[i].size),
8437f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski                                static_cast<size_t>(pMemRanges[i].offset), static_cast<size_t>(data_end),
8438315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                validation_error_map[VALIDATION_ERROR_0c20055a]);
8439f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski                }
84405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
84415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
84425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
8443c7ee6f2fe100c1aacfaa0872832717c906bb8a4aMark Lobodzinski    return skip;
84445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
84455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
8446bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinskistatic bool ValidateAndCopyNoncoherentMemoryToDriver(layer_data *dev_data, uint32_t mem_range_count,
8447bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski                                                     const VkMappedMemoryRange *mem_ranges) {
8448bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski    bool skip = false;
8449bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski    for (uint32_t i = 0; i < mem_range_count; ++i) {
84509a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto mem_info = GetMemObjInfo(dev_data, mem_ranges[i].memory);
845157fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis        if (mem_info) {
84525f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            if (mem_info->shadow_copy) {
84535f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski                VkDeviceSize size = (mem_info->mem_range.size != VK_WHOLE_SIZE)
84545f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski                                        ? mem_info->mem_range.size
8455d8a53ade6b5501256798a8b4ec0bc14f72adc1faTobin Ehlis                                        : (mem_info->alloc_info.allocationSize - mem_info->mem_range.offset);
84565f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski                char *data = static_cast<char *>(mem_info->shadow_copy);
84575f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski                for (uint64_t j = 0; j < mem_info->shadow_pad_size; ++j) {
84585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    if (data[j] != NoncoherentMemoryFillValue) {
84599b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        skip |= log_msg(
84609b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
84619b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(mem_ranges[i].memory), __LINE__, MEMTRACK_INVALID_MAP, "MEM",
84629b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            "Memory underflow was detected on mem obj 0x%" PRIxLEAST64, HandleToUint64(mem_ranges[i].memory));
84635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    }
84645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
84655f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski                for (uint64_t j = (size + mem_info->shadow_pad_size); j < (2 * mem_info->shadow_pad_size + size); ++j) {
84665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    if (data[j] != NoncoherentMemoryFillValue) {
84679b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        skip |= log_msg(
84689b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
84699b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(mem_ranges[i].memory), __LINE__, MEMTRACK_INVALID_MAP, "MEM",
84709b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            "Memory overflow was detected on mem obj 0x%" PRIxLEAST64, HandleToUint64(mem_ranges[i].memory));
84715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    }
84725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
84735f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski                memcpy(mem_info->p_driver_data, static_cast<void *>(data + mem_info->shadow_pad_size), (size_t)(size));
84745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
84755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
84765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
8477bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski    return skip;
84785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
84795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
8480bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinskistatic void CopyNoncoherentMemoryFromDriver(layer_data *dev_data, uint32_t mem_range_count, const VkMappedMemoryRange *mem_ranges) {
8481bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski    for (uint32_t i = 0; i < mem_range_count; ++i) {
84829a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto mem_info = GetMemObjInfo(dev_data, mem_ranges[i].memory);
84835f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski        if (mem_info && mem_info->shadow_copy) {
84845f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            VkDeviceSize size = (mem_info->mem_range.size != VK_WHOLE_SIZE)
84855f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski                                    ? mem_info->mem_range.size
84865f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski                                    : (mem_info->alloc_info.allocationSize - mem_ranges[i].offset);
84875f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            char *data = static_cast<char *>(mem_info->shadow_copy);
84885f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            memcpy(data + mem_info->shadow_pad_size, mem_info->p_driver_data, (size_t)(size));
84899e21e56fc23ade48efd3752d2e2729895eb90349Mark Lobodzinski        }
84909e21e56fc23ade48efd3752d2e2729895eb90349Mark Lobodzinski    }
84919e21e56fc23ade48efd3752d2e2729895eb90349Mark Lobodzinski}
84929e21e56fc23ade48efd3752d2e2729895eb90349Mark Lobodzinski
8493ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinskistatic bool ValidateMappedMemoryRangeDeviceLimits(layer_data *dev_data, const char *func_name, uint32_t mem_range_count,
8494ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski                                                  const VkMappedMemoryRange *mem_ranges) {
8495ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski    bool skip = false;
8496ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski    for (uint32_t i = 0; i < mem_range_count; ++i) {
8497ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski        uint64_t atom_size = dev_data->phys_dev_properties.properties.limits.nonCoherentAtomSize;
849816769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton        if (SafeModulo(mem_ranges[i].offset, atom_size) != 0) {
8499df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
8500315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(mem_ranges->memory), __LINE__, VALIDATION_ERROR_0c20055e, "MEM",
8501ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski                            "%s: Offset in pMemRanges[%d] is 0x%" PRIxLEAST64
8502ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski                            ", which is not a multiple of VkPhysicalDeviceLimits::nonCoherentAtomSize (0x%" PRIxLEAST64 "). %s",
8503315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            func_name, i, mem_ranges[i].offset, atom_size, validation_error_map[VALIDATION_ERROR_0c20055e]);
8504ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski        }
850516769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton        if ((mem_ranges[i].size != VK_WHOLE_SIZE) && (SafeModulo(mem_ranges[i].size, atom_size) != 0)) {
8506df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
8507315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(mem_ranges->memory), __LINE__, VALIDATION_ERROR_0c200560, "MEM",
8508ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski                            "%s: Size in pMemRanges[%d] is 0x%" PRIxLEAST64
8509ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski                            ", which is not a multiple of VkPhysicalDeviceLimits::nonCoherentAtomSize (0x%" PRIxLEAST64 "). %s",
8510315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            func_name, i, mem_ranges[i].size, atom_size, validation_error_map[VALIDATION_ERROR_0c200560]);
8511ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski        }
8512ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski    }
8513ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski    return skip;
8514ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski}
8515ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski
851680e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinskistatic bool PreCallValidateFlushMappedMemoryRanges(layer_data *dev_data, uint32_t mem_range_count,
851780e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski                                                   const VkMappedMemoryRange *mem_ranges) {
851880e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski    bool skip = false;
8519ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    lock_guard_t lock(global_lock);
852080e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski    skip |= ValidateAndCopyNoncoherentMemoryToDriver(dev_data, mem_range_count, mem_ranges);
852180e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski    skip |= validateMemoryIsMapped(dev_data, "vkFlushMappedMemoryRanges", mem_range_count, mem_ranges);
852280e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski    return skip;
852380e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski}
852480e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski
8525bba0de708d942e9a2187158915856995db1c5a4dMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL FlushMappedMemoryRanges(VkDevice device, uint32_t memRangeCount,
8526bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski                                                       const VkMappedMemoryRange *pMemRanges) {
85275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
852856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
85295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
853080e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski    if (!PreCallValidateFlushMappedMemoryRanges(dev_data, memRangeCount, pMemRanges)) {
85314a0754042cf090e131e9e769d8a3633c228625beChris Forbes        result = dev_data->dispatch_table.FlushMappedMemoryRanges(device, memRangeCount, pMemRanges);
85325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
85335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
85345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
85355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
853680e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinskistatic bool PreCallValidateInvalidateMappedMemoryRanges(layer_data *dev_data, uint32_t mem_range_count,
853780e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski                                                        const VkMappedMemoryRange *mem_ranges) {
853880e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski    bool skip = false;
8539ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    lock_guard_t lock(global_lock);
854080e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski    skip |= validateMemoryIsMapped(dev_data, "vkInvalidateMappedMemoryRanges", mem_range_count, mem_ranges);
854180e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski    return skip;
854280e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski}
854380e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski
854480e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinskistatic void PostCallRecordInvalidateMappedMemoryRanges(layer_data *dev_data, uint32_t mem_range_count,
854580e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski                                                       const VkMappedMemoryRange *mem_ranges) {
8546ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    lock_guard_t lock(global_lock);
854780e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski    // Update our shadow copy with modified driver data
854880e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski    CopyNoncoherentMemoryFromDriver(dev_data, mem_range_count, mem_ranges);
854980e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski}
855080e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski
8551bba0de708d942e9a2187158915856995db1c5a4dMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL InvalidateMappedMemoryRanges(VkDevice device, uint32_t memRangeCount,
8552bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski                                                            const VkMappedMemoryRange *pMemRanges) {
85535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
855456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
85555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
855680e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski    if (!PreCallValidateInvalidateMappedMemoryRanges(dev_data, memRangeCount, pMemRanges)) {
85574a0754042cf090e131e9e769d8a3633c228625beChris Forbes        result = dev_data->dispatch_table.InvalidateMappedMemoryRanges(device, memRangeCount, pMemRanges);
855880e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski        if (result == VK_SUCCESS) {
855980e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski            PostCallRecordInvalidateMappedMemoryRanges(dev_data, memRangeCount, pMemRanges);
856080e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski        }
85615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
85625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
85635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
85645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
8565160335c453ec51cc48bdef78e8befdb3c86ff292Cort Strattonstatic bool PreCallValidateBindImageMemory(layer_data *dev_data, VkImage image, IMAGE_STATE *image_state, VkDeviceMemory mem,
8566160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton                                           VkDeviceSize memoryOffset) {
85670109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski    bool skip = false;
85681facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis    if (image_state) {
8569ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes        unique_lock_t lock(global_lock);
857094c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis        // Track objects tied to memory
85719b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus        uint64_t image_handle = HandleToUint64(image);
85727a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski        skip = ValidateSetMemBinding(dev_data, mem, image_handle, kVulkanObjectTypeImage, "vkBindImageMemory()");
8573ff3ef1181960319d2268e82dae075726f650c553Tobin Ehlis        if (!image_state->memory_requirements_checked) {
8574ff3ef1181960319d2268e82dae075726f650c553Tobin Ehlis            // There's not an explicit requirement in the spec to call vkGetImageMemoryRequirements() prior to calling
8575341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton            // BindImageMemory but it's implied in that memory being bound must conform with VkMemoryRequirements from
8576341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton            // vkGetImageMemoryRequirements()
85770109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
85780109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski                            image_handle, __LINE__, DRAWSTATE_INVALID_IMAGE, "DS",
85790109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski                            "vkBindImageMemory(): Binding memory to image 0x%" PRIxLEAST64
85800109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski                            " but vkGetImageMemoryRequirements() has not been called on that image.",
85810109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski                            image_handle);
8582ff3ef1181960319d2268e82dae075726f650c553Tobin Ehlis            // Make the call for them so we can verify the state
8583ff3ef1181960319d2268e82dae075726f650c553Tobin Ehlis            lock.unlock();
8584341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton            dev_data->dispatch_table.GetImageMemoryRequirements(dev_data->device, image, &image_state->requirements);
8585ff3ef1181960319d2268e82dae075726f650c553Tobin Ehlis            lock.lock();
8586ff3ef1181960319d2268e82dae075726f650c553Tobin Ehlis        }
858747aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski
85880ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton        // Validate bound memory range information
85899a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto mem_info = GetMemObjInfo(dev_data, mem);
859057fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis        if (mem_info) {
85910ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton            skip |= ValidateInsertImageMemoryRange(dev_data, image, mem_info, memoryOffset, image_state->requirements,
85920ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton                                                   image_state->createInfo.tiling == VK_IMAGE_TILING_LINEAR, "vkBindImageMemory()");
859374300755ed9ec780d6073af71e47f201217008d6Cort Stratton            skip |= ValidateMemoryTypes(dev_data, mem_info, image_state->requirements.memoryTypeBits, "vkBindImageMemory()",
8594315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                        VALIDATION_ERROR_1740082e);
859547aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski        }
8596160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton
8597160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton        // Validate memory requirements alignment
859816769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton        if (SafeModulo(memoryOffset, image_state->requirements.alignment) != 0) {
8599160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
8600315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            image_handle, __LINE__, VALIDATION_ERROR_17400830, "DS",
8601160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton                            "vkBindImageMemory(): memoryOffset is 0x%" PRIxLEAST64
8602160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton                            " but must be an integer multiple of the "
8603160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton                            "VkMemoryRequirements::alignment value 0x%" PRIxLEAST64
8604160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton                            ", returned from a call to vkGetImageMemoryRequirements with image. %s",
8605315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            memoryOffset, image_state->requirements.alignment, validation_error_map[VALIDATION_ERROR_17400830]);
8606160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton        }
8607160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton
8608160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton        // Validate memory requirements size
8609160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton        if (image_state->requirements.size > mem_info->alloc_info.allocationSize - memoryOffset) {
8610160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
8611315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            image_handle, __LINE__, VALIDATION_ERROR_17400832, "DS",
8612160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton                            "vkBindImageMemory(): memory size minus memoryOffset is 0x%" PRIxLEAST64
8613160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton                            " but must be at least as large as "
8614160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton                            "VkMemoryRequirements::size value 0x%" PRIxLEAST64
8615160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton                            ", returned from a call to vkGetImageMemoryRequirements with image. %s",
8616160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton                            mem_info->alloc_info.allocationSize - memoryOffset, image_state->requirements.size,
8617315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            validation_error_map[VALIDATION_ERROR_17400832]);
8618160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton        }
8619341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton    }
8620341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton    return skip;
8621341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton}
862247aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski
8623160335c453ec51cc48bdef78e8befdb3c86ff292Cort Strattonstatic void PostCallRecordBindImageMemory(layer_data *dev_data, VkImage image, IMAGE_STATE *image_state, VkDeviceMemory mem,
8624160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton                                          VkDeviceSize memoryOffset) {
8625341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton    if (image_state) {
8626ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes        unique_lock_t lock(global_lock);
86270ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton        // Track bound memory range information
86280ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton        auto mem_info = GetMemObjInfo(dev_data, mem);
86290ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton        if (mem_info) {
86300ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton            InsertImageMemoryRange(dev_data, image, mem_info, memoryOffset, image_state->requirements,
86310ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton                                   image_state->createInfo.tiling == VK_IMAGE_TILING_LINEAR);
86320ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton        }
86330ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton
8634c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton        // Track objects tied to memory
86359b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus        uint64_t image_handle = HandleToUint64(image);
86367a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski        SetMemBinding(dev_data, mem, image_handle, kVulkanObjectTypeImage, "vkBindImageMemory()");
8637c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton
8638341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton        image_state->binding.mem = mem;
8639341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton        image_state->binding.offset = memoryOffset;
8640341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton        image_state->binding.size = image_state->requirements.size;
8641341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton    }
8642341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton}
8643341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton
8644341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort StrattonVKAPI_ATTR VkResult VKAPI_CALL BindImageMemory(VkDevice device, VkImage image, VkDeviceMemory mem, VkDeviceSize memoryOffset) {
8645341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
8646341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
8647160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton    auto image_state = GetImageState(dev_data, image);
8648160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton    bool skip = PreCallValidateBindImageMemory(dev_data, image, image_state, mem, memoryOffset);
8649341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton    if (!skip) {
8650341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton        result = dev_data->dispatch_table.BindImageMemory(device, image, mem, memoryOffset);
8651341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton        if (result == VK_SUCCESS) {
8652160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton            PostCallRecordBindImageMemory(dev_data, image, image_state, mem, memoryOffset);
865394c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis        }
86545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
86555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
86565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
86575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
865889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL SetEvent(VkDevice device, VkEvent event) {
86593251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
86603ee1d6057ee6c49b9dbbeb067b7fd149bdba7b5cTobin Ehlis    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
866156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
8662ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
86639a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto event_state = GetEventNode(dev_data, event);
86644710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis    if (event_state) {
86654710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis        event_state->needsSignaled = false;
86664710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis        event_state->stageMask = VK_PIPELINE_STAGE_HOST_BIT;
86674710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis        if (event_state->write_in_use) {
86683251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT,
86699b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(event), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS",
86703251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "Cannot call vkSetEvent() on event 0x%" PRIxLEAST64 " that is already in use by a command buffer.",
86719b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(event));
86723ee1d6057ee6c49b9dbbeb067b7fd149bdba7b5cTobin Ehlis        }
86733ee1d6057ee6c49b9dbbeb067b7fd149bdba7b5cTobin Ehlis    }
8674b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
86756fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis    // Host setting event is visible to all queues immediately so update stageMask for any queue that's seen this event
86766fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis    // TODO : For correctness this needs separate fix to verify that app doesn't make incorrect assumptions about the
86776fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis    // ordering of this command in relation to vkCmd[Set|Reset]Events (see GH297)
86786fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis    for (auto queue_data : dev_data->queueMap) {
86796fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis        auto event_entry = queue_data.second.eventToStageMap.find(event);
86806fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis        if (event_entry != queue_data.second.eventToStageMap.end()) {
86816fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis            event_entry->second |= VK_PIPELINE_STAGE_HOST_BIT;
86826fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis        }
86836fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis    }
86843251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (!skip) result = dev_data->dispatch_table.SetEvent(device, event);
86855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
86865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
86875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
8688bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL QueueBindSparse(VkQueue queue, uint32_t bindInfoCount, const VkBindSparseInfo *pBindInfo,
8689bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                               VkFence fence) {
869056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map);
86915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
86923251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
8693ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
86949a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto pFence = GetFenceNode(dev_data, fence);
86959a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto pQueue = GetQueueState(dev_data, queue);
8696651d92815dfff917308137bb67aacccc4f60df86Chris Forbes
86974b38d3aa8b6be6a7f5bebb472ab439da0562824fTobin Ehlis    // First verify that fence is not in use
86983251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    skip |= ValidateFenceForSubmit(dev_data, pFence);
8699651d92815dfff917308137bb67aacccc4f60df86Chris Forbes
87009867daedbf52debc77d6568162ee21e071699b80Chris Forbes    if (pFence) {
870193ccd9708dad3ffb58a3fc09a3d61cc5fe1569f8Mark Lobodzinski        SubmitFence(pQueue, pFence, std::max(1u, bindInfoCount));
87024b38d3aa8b6be6a7f5bebb472ab439da0562824fTobin Ehlis    }
8703651d92815dfff917308137bb67aacccc4f60df86Chris Forbes
87041344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis    for (uint32_t bindIdx = 0; bindIdx < bindInfoCount; ++bindIdx) {
87051344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis        const VkBindSparseInfo &bindInfo = pBindInfo[bindIdx];
87065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // Track objects tied to memory
87071344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis        for (uint32_t j = 0; j < bindInfo.bufferBindCount; j++) {
87081344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis            for (uint32_t k = 0; k < bindInfo.pBufferBinds[j].bindCount; k++) {
8709f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis                auto sparse_binding = bindInfo.pBufferBinds[j].pBinds[k];
8710f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis                if (SetSparseMemBinding(dev_data, {sparse_binding.memory, sparse_binding.memoryOffset, sparse_binding.size},
87119b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                        HandleToUint64(bindInfo.pBufferBinds[j].buffer), kVulkanObjectTypeBuffer))
87123251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip = true;
87135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
87145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
87151344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis        for (uint32_t j = 0; j < bindInfo.imageOpaqueBindCount; j++) {
87161344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis            for (uint32_t k = 0; k < bindInfo.pImageOpaqueBinds[j].bindCount; k++) {
8717f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis                auto sparse_binding = bindInfo.pImageOpaqueBinds[j].pBinds[k];
8718f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis                if (SetSparseMemBinding(dev_data, {sparse_binding.memory, sparse_binding.memoryOffset, sparse_binding.size},
87199b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                        HandleToUint64(bindInfo.pImageOpaqueBinds[j].image), kVulkanObjectTypeImage))
87203251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip = true;
87215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
87225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
87231344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis        for (uint32_t j = 0; j < bindInfo.imageBindCount; j++) {
87241344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis            for (uint32_t k = 0; k < bindInfo.pImageBinds[j].bindCount; k++) {
8725f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis                auto sparse_binding = bindInfo.pImageBinds[j].pBinds[k];
8726f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis                // TODO: This size is broken for non-opaque bindings, need to update to comprehend full sparse binding data
8727f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis                VkDeviceSize size = sparse_binding.extent.depth * sparse_binding.extent.height * sparse_binding.extent.width * 4;
8728f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis                if (SetSparseMemBinding(dev_data, {sparse_binding.memory, sparse_binding.memoryOffset, size},
87299b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                        HandleToUint64(bindInfo.pImageBinds[j].image), kVulkanObjectTypeImage))
87303251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip = true;
87315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
87325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
87339867daedbf52debc77d6568162ee21e071699b80Chris Forbes
87349867daedbf52debc77d6568162ee21e071699b80Chris Forbes        std::vector<SEMAPHORE_WAIT> semaphore_waits;
87359867daedbf52debc77d6568162ee21e071699b80Chris Forbes        std::vector<VkSemaphore> semaphore_signals;
87361344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis        for (uint32_t i = 0; i < bindInfo.waitSemaphoreCount; ++i) {
873701a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes            VkSemaphore semaphore = bindInfo.pWaitSemaphores[i];
87389a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            auto pSemaphore = GetSemaphoreNode(dev_data, semaphore);
873901a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes            if (pSemaphore) {
874001a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes                if (pSemaphore->signaled) {
87419867daedbf52debc77d6568162ee21e071699b80Chris Forbes                    if (pSemaphore->signaler.first != VK_NULL_HANDLE) {
87429867daedbf52debc77d6568162ee21e071699b80Chris Forbes                        semaphore_waits.push_back({semaphore, pSemaphore->signaler.first, pSemaphore->signaler.second});
87439867daedbf52debc77d6568162ee21e071699b80Chris Forbes                        pSemaphore->in_use.fetch_add(1);
87449867daedbf52debc77d6568162ee21e071699b80Chris Forbes                    }
87459867daedbf52debc77d6568162ee21e071699b80Chris Forbes                    pSemaphore->signaler.first = VK_NULL_HANDLE;
874601a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes                    pSemaphore->signaled = false;
87471344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis                } else {
87483251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT,
87499b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                    HandleToUint64(semaphore), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS",
87503251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    "vkQueueBindSparse: Queue 0x%p is waiting on semaphore 0x%" PRIx64
87513251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    " that has no way to be signaled.",
87529b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                    queue, HandleToUint64(semaphore));
87535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
87545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
87555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
87561344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis        for (uint32_t i = 0; i < bindInfo.signalSemaphoreCount; ++i) {
875701a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes            VkSemaphore semaphore = bindInfo.pSignalSemaphores[i];
87589a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            auto pSemaphore = GetSemaphoreNode(dev_data, semaphore);
875901a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes            if (pSemaphore) {
876001a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes                if (pSemaphore->signaled) {
87613251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT,
87629b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                   HandleToUint64(semaphore), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS",
87633251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                   "vkQueueBindSparse: Queue 0x%p is signaling semaphore 0x%" PRIx64
87643251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                   ", but that semaphore is already signaled.",
87659b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                   queue, HandleToUint64(semaphore));
8766bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                } else {
87679867daedbf52debc77d6568162ee21e071699b80Chris Forbes                    pSemaphore->signaler.first = queue;
87689867daedbf52debc77d6568162ee21e071699b80Chris Forbes                    pSemaphore->signaler.second = pQueue->seq + pQueue->submissions.size() + 1;
87699867daedbf52debc77d6568162ee21e071699b80Chris Forbes                    pSemaphore->signaled = true;
87709867daedbf52debc77d6568162ee21e071699b80Chris Forbes                    pSemaphore->in_use.fetch_add(1);
87719867daedbf52debc77d6568162ee21e071699b80Chris Forbes                    semaphore_signals.push_back(semaphore);
87729867daedbf52debc77d6568162ee21e071699b80Chris Forbes                }
87735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
87745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
87759867daedbf52debc77d6568162ee21e071699b80Chris Forbes
8776bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        pQueue->submissions.emplace_back(std::vector<VkCommandBuffer>(), semaphore_waits, semaphore_signals,
87779867daedbf52debc77d6568162ee21e071699b80Chris Forbes                                         bindIdx == bindInfoCount - 1 ? fence : VK_NULL_HANDLE);
87785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
87799867daedbf52debc77d6568162ee21e071699b80Chris Forbes
87809867daedbf52debc77d6568162ee21e071699b80Chris Forbes    if (pFence && !bindInfoCount) {
87819867daedbf52debc77d6568162ee21e071699b80Chris Forbes        // No work to do, just dropping a fence in the queue by itself.
8782bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        pQueue->submissions.emplace_back(std::vector<VkCommandBuffer>(), std::vector<SEMAPHORE_WAIT>(), std::vector<VkSemaphore>(),
87839867daedbf52debc77d6568162ee21e071699b80Chris Forbes                                         fence);
87849867daedbf52debc77d6568162ee21e071699b80Chris Forbes    }
87859867daedbf52debc77d6568162ee21e071699b80Chris Forbes
8786b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
87875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
87883251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (!skip) return dev_data->dispatch_table.QueueBindSparse(queue, bindInfoCount, pBindInfo, fence);
87895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
87905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
87915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
87925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
879389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateSemaphore(VkDevice device, const VkSemaphoreCreateInfo *pCreateInfo,
879489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                               const VkAllocationCallbacks *pAllocator, VkSemaphore *pSemaphore) {
879556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
87964a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.CreateSemaphore(device, pCreateInfo, pAllocator, pSemaphore);
87975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (result == VK_SUCCESS) {
8798ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes        lock_guard_t lock(global_lock);
8799bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        SEMAPHORE_NODE *sNode = &dev_data->semaphoreMap[*pSemaphore];
88009867daedbf52debc77d6568162ee21e071699b80Chris Forbes        sNode->signaler.first = VK_NULL_HANDLE;
88019867daedbf52debc77d6568162ee21e071699b80Chris Forbes        sNode->signaler.second = 0;
88021344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis        sNode->signaled = false;
88035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
88045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
88055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
88065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
8807bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateEvent(VkDevice device, const VkEventCreateInfo *pCreateInfo,
8808bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                           const VkAllocationCallbacks *pAllocator, VkEvent *pEvent) {
880956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
88104a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.CreateEvent(device, pCreateInfo, pAllocator, pEvent);
88115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (result == VK_SUCCESS) {
8812ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes        lock_guard_t lock(global_lock);
88135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        dev_data->eventMap[*pEvent].needsSignaled = false;
8814293ecfc5e69ed3978a8c04518166d828294870a4Tony Barbour        dev_data->eventMap[*pEvent].write_in_use = 0;
88155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        dev_data->eventMap[*pEvent].stageMask = VkPipelineStageFlags(0);
88165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
88175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
88185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
88195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
88209ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinskistatic bool PreCallValidateCreateSwapchainKHR(layer_data *dev_data, const char *func_name,
88219ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                                              VkSwapchainCreateInfoKHR const *pCreateInfo, SURFACE_STATE *surface_state,
88229ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                                              SWAPCHAIN_NODE *old_swapchain_state) {
8823d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes    auto most_recent_swapchain = surface_state->swapchain ? surface_state->swapchain : surface_state->old_swapchain;
8824d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes
88254bd5f453535de3d3423ff1f9995b4acb15f791d2Chris Forbes    // TODO: revisit this. some of these rules are being relaxed.
88260bbc015828bdb99e85e6731ce92428557902701fPetr Kraus
88270bbc015828bdb99e85e6731ce92428557902701fPetr Kraus    // All physical devices and queue families are required to be able
88280bbc015828bdb99e85e6731ce92428557902701fPetr Kraus    // to present to any native window on Android; require the
88290bbc015828bdb99e85e6731ce92428557902701fPetr Kraus    // application to have established support on any other platform.
8830d4eaca34eca7f4b4e34190c441a579347bb2016aMark Lobodzinski    if (!dev_data->instance_data->extensions.vk_khr_android_surface) {
88310bbc015828bdb99e85e6731ce92428557902701fPetr Kraus        auto support_predicate = [dev_data](decltype(surface_state->gpu_queue_support)::const_reference qs) -> bool {
88320bbc015828bdb99e85e6731ce92428557902701fPetr Kraus            // TODO: should restrict search only to queue families of VkDeviceQueueCreateInfos, not whole phys. device
88330bbc015828bdb99e85e6731ce92428557902701fPetr Kraus            return (qs.first.gpu == dev_data->physical_device) && qs.second;
88340bbc015828bdb99e85e6731ce92428557902701fPetr Kraus        };
88350bbc015828bdb99e85e6731ce92428557902701fPetr Kraus        const auto& support = surface_state->gpu_queue_support;
88360bbc015828bdb99e85e6731ce92428557902701fPetr Kraus        bool is_supported = std::any_of(support.begin(), support.end(), support_predicate);
88370bbc015828bdb99e85e6731ce92428557902701fPetr Kraus
88380bbc015828bdb99e85e6731ce92428557902701fPetr Kraus        if (!is_supported) {
88390bbc015828bdb99e85e6731ce92428557902701fPetr Kraus            if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
8840315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(dev_data->device), __LINE__, VALIDATION_ERROR_146009ec, "DS",
88410bbc015828bdb99e85e6731ce92428557902701fPetr Kraus                        "%s: pCreateInfo->surface is not known at this time to be supported for presentation by this device. "
88420bbc015828bdb99e85e6731ce92428557902701fPetr Kraus                        "The vkGetPhysicalDeviceSurfaceSupportKHR() must be called beforehand, and it must return VK_TRUE support "
88430bbc015828bdb99e85e6731ce92428557902701fPetr Kraus                        "with this surface for at least one queue family of this device. %s",
8844315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        func_name, validation_error_map[VALIDATION_ERROR_146009ec]))
88450bbc015828bdb99e85e6731ce92428557902701fPetr Kraus                return true;
88460bbc015828bdb99e85e6731ce92428557902701fPetr Kraus        }
88470bbc015828bdb99e85e6731ce92428557902701fPetr Kraus    }
88480bbc015828bdb99e85e6731ce92428557902701fPetr Kraus
8849d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes    if (most_recent_swapchain != old_swapchain_state || (surface_state->old_swapchain && surface_state->swapchain)) {
8850d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes        if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
88519b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                    HandleToUint64(dev_data->device), __LINE__, DRAWSTATE_SWAPCHAIN_ALREADY_EXISTS, "DS",
88529ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                    "%s: surface has an existing swapchain other than oldSwapchain", func_name))
8853d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes            return true;
8854d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes    }
8855d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes    if (old_swapchain_state && old_swapchain_state->createInfo.surface != pCreateInfo->surface) {
8856d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes        if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
88579b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                    HandleToUint64(pCreateInfo->oldSwapchain), __LINE__, DRAWSTATE_SWAPCHAIN_WRONG_SURFACE, "DS",
88589b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                    "%s: pCreateInfo->oldSwapchain's surface is not pCreateInfo->surface", func_name))
8859d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes            return true;
8860d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes    }
88619a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto physical_device_state = GetPhysicalDeviceState(dev_data->instance_data, dev_data->physical_device);
88627de258f87ca1192db116a66b209253793d276ebcChris Forbes    if (physical_device_state->vkGetPhysicalDeviceSurfaceCapabilitiesKHRState == UNCALLED) {
88637de258f87ca1192db116a66b209253793d276ebcChris Forbes        if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
88649b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                    HandleToUint64(dev_data->physical_device), __LINE__, DRAWSTATE_SWAPCHAIN_CREATE_BEFORE_QUERY, "DS",
88659ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                    "%s: surface capabilities not retrieved for this physical device", func_name))
88667de258f87ca1192db116a66b209253793d276ebcChris Forbes            return true;
8867cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    } else {  // have valid capabilities
88685c99b4daed164798f307244c9bde17b4f66014fbChris Forbes        auto &capabilities = physical_device_state->surfaceCapabilities;
88699ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski        // Validate pCreateInfo->minImageCount against VkSurfaceCapabilitiesKHR::{min|max}ImageCount:
88702fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen        if (pCreateInfo->minImageCount < capabilities.minImageCount) {
88712fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen            if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
8872315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(dev_data->device), __LINE__, VALIDATION_ERROR_146009ee, "DS",
88739ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                        "%s called with minImageCount = %d, which is outside the bounds returned "
88742fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen                        "by vkGetPhysicalDeviceSurfaceCapabilitiesKHR() (i.e. minImageCount = %d, maxImageCount = %d). %s",
88759ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                        func_name, pCreateInfo->minImageCount, capabilities.minImageCount, capabilities.maxImageCount,
8876315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_146009ee]))
88772fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen                return true;
88782fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen        }
88792fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen
88802fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen        if ((capabilities.maxImageCount > 0) && (pCreateInfo->minImageCount > capabilities.maxImageCount)) {
88815c99b4daed164798f307244c9bde17b4f66014fbChris Forbes            if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
8882315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(dev_data->device), __LINE__, VALIDATION_ERROR_146009f0, "DS",
88839ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                        "%s called with minImageCount = %d, which is outside the bounds returned "
88842fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen                        "by vkGetPhysicalDeviceSurfaceCapabilitiesKHR() (i.e. minImageCount = %d, maxImageCount = %d). %s",
88859ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                        func_name, pCreateInfo->minImageCount, capabilities.minImageCount, capabilities.maxImageCount,
8886315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_146009f0]))
88875c99b4daed164798f307244c9bde17b4f66014fbChris Forbes                return true;
88885c99b4daed164798f307244c9bde17b4f66014fbChris Forbes        }
88892fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen
88909ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski        // Validate pCreateInfo->imageExtent against VkSurfaceCapabilitiesKHR::{current|min|max}ImageExtent:
88912e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill        if ((capabilities.currentExtent.width == kSurfaceSizeFromSwapchain) &&
88922e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill            ((pCreateInfo->imageExtent.width < capabilities.minImageExtent.width) ||
88932e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill             (pCreateInfo->imageExtent.width > capabilities.maxImageExtent.width) ||
88942e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill             (pCreateInfo->imageExtent.height < capabilities.minImageExtent.height) ||
88952e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill             (pCreateInfo->imageExtent.height > capabilities.maxImageExtent.height))) {
88965c99b4daed164798f307244c9bde17b4f66014fbChris Forbes            if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
8897315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(dev_data->device), __LINE__, VALIDATION_ERROR_146009f4, "DS",
88989ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                        "%s called with imageExtent = (%d,%d), which is outside the bounds returned by "
88999ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                        "vkGetPhysicalDeviceSurfaceCapabilitiesKHR(): currentExtent = (%d,%d), minImageExtent = (%d,%d), "
89009ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                        "maxImageExtent = (%d,%d). %s",
89019ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                        func_name, pCreateInfo->imageExtent.width, pCreateInfo->imageExtent.height,
89029ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                        capabilities.currentExtent.width, capabilities.currentExtent.height, capabilities.minImageExtent.width,
89039ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                        capabilities.minImageExtent.height, capabilities.maxImageExtent.width, capabilities.maxImageExtent.height,
8904315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_146009f4]))
89055c99b4daed164798f307244c9bde17b4f66014fbChris Forbes                return true;
89065c99b4daed164798f307244c9bde17b4f66014fbChris Forbes        }
89079ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski        // pCreateInfo->preTransform should have exactly one bit set, and that bit must also be set in
89089ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski        // VkSurfaceCapabilitiesKHR::supportedTransforms.
89095c99b4daed164798f307244c9bde17b4f66014fbChris Forbes        if (!pCreateInfo->preTransform || (pCreateInfo->preTransform & (pCreateInfo->preTransform - 1)) ||
89105c99b4daed164798f307244c9bde17b4f66014fbChris Forbes            !(pCreateInfo->preTransform & capabilities.supportedTransforms)) {
89119ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski            // This is an error situation; one for which we'd like to give the developer a helpful, multi-line error message.  Build
89129ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski            // it up a little at a time, and then log it:
89135c99b4daed164798f307244c9bde17b4f66014fbChris Forbes            std::string errorString = "";
89145c99b4daed164798f307244c9bde17b4f66014fbChris Forbes            char str[1024];
89155c99b4daed164798f307244c9bde17b4f66014fbChris Forbes            // Here's the first part of the message:
89169ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski            sprintf(str, "%s called with a non-supported pCreateInfo->preTransform (i.e. %s).  Supported values are:\n", func_name,
89175c99b4daed164798f307244c9bde17b4f66014fbChris Forbes                    string_VkSurfaceTransformFlagBitsKHR(pCreateInfo->preTransform));
89185c99b4daed164798f307244c9bde17b4f66014fbChris Forbes            errorString += str;
89195c99b4daed164798f307244c9bde17b4f66014fbChris Forbes            for (int i = 0; i < 32; i++) {
89205c99b4daed164798f307244c9bde17b4f66014fbChris Forbes                // Build up the rest of the message:
89215c99b4daed164798f307244c9bde17b4f66014fbChris Forbes                if ((1 << i) & capabilities.supportedTransforms) {
89225c99b4daed164798f307244c9bde17b4f66014fbChris Forbes                    const char *newStr = string_VkSurfaceTransformFlagBitsKHR((VkSurfaceTransformFlagBitsKHR)(1 << i));
89235c99b4daed164798f307244c9bde17b4f66014fbChris Forbes                    sprintf(str, "    %s\n", newStr);
89245c99b4daed164798f307244c9bde17b4f66014fbChris Forbes                    errorString += str;
89255c99b4daed164798f307244c9bde17b4f66014fbChris Forbes                }
89265c99b4daed164798f307244c9bde17b4f66014fbChris Forbes            }
89275c99b4daed164798f307244c9bde17b4f66014fbChris Forbes            // Log the message that we've built up:
89285c99b4daed164798f307244c9bde17b4f66014fbChris Forbes            if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
8929315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(dev_data->device), __LINE__, VALIDATION_ERROR_146009fe, "DS", "%s. %s", errorString.c_str(),
8930315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_146009fe]))
89315c99b4daed164798f307244c9bde17b4f66014fbChris Forbes                return true;
89325c99b4daed164798f307244c9bde17b4f66014fbChris Forbes        }
89337b0d28d116977b91892f354e002edd760bdb86cbChris Forbes
89349ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski        // pCreateInfo->compositeAlpha should have exactly one bit set, and that bit must also be set in
89359ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski        // VkSurfaceCapabilitiesKHR::supportedCompositeAlpha
89365c99b4daed164798f307244c9bde17b4f66014fbChris Forbes        if (!pCreateInfo->compositeAlpha || (pCreateInfo->compositeAlpha & (pCreateInfo->compositeAlpha - 1)) ||
89375c99b4daed164798f307244c9bde17b4f66014fbChris Forbes            !((pCreateInfo->compositeAlpha) & capabilities.supportedCompositeAlpha)) {
89389ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski            // This is an error situation; one for which we'd like to give the developer a helpful, multi-line error message.  Build
89399ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski            // it up a little at a time, and then log it:
89405c99b4daed164798f307244c9bde17b4f66014fbChris Forbes            std::string errorString = "";
89415c99b4daed164798f307244c9bde17b4f66014fbChris Forbes            char str[1024];
89425c99b4daed164798f307244c9bde17b4f66014fbChris Forbes            // Here's the first part of the message:
89439ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski            sprintf(str, "%s called with a non-supported pCreateInfo->compositeAlpha (i.e. %s).  Supported values are:\n",
89449ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                    func_name, string_VkCompositeAlphaFlagBitsKHR(pCreateInfo->compositeAlpha));
89455c99b4daed164798f307244c9bde17b4f66014fbChris Forbes            errorString += str;
89465c99b4daed164798f307244c9bde17b4f66014fbChris Forbes            for (int i = 0; i < 32; i++) {
89475c99b4daed164798f307244c9bde17b4f66014fbChris Forbes                // Build up the rest of the message:
89485c99b4daed164798f307244c9bde17b4f66014fbChris Forbes                if ((1 << i) & capabilities.supportedCompositeAlpha) {
89495c99b4daed164798f307244c9bde17b4f66014fbChris Forbes                    const char *newStr = string_VkCompositeAlphaFlagBitsKHR((VkCompositeAlphaFlagBitsKHR)(1 << i));
89505c99b4daed164798f307244c9bde17b4f66014fbChris Forbes                    sprintf(str, "    %s\n", newStr);
89515c99b4daed164798f307244c9bde17b4f66014fbChris Forbes                    errorString += str;
89525c99b4daed164798f307244c9bde17b4f66014fbChris Forbes                }
89535c99b4daed164798f307244c9bde17b4f66014fbChris Forbes            }
89545c99b4daed164798f307244c9bde17b4f66014fbChris Forbes            // Log the message that we've built up:
89555c99b4daed164798f307244c9bde17b4f66014fbChris Forbes            if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
8956315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(dev_data->device), __LINE__, VALIDATION_ERROR_14600a00, "DS", "%s. %s", errorString.c_str(),
8957315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_14600a00]))
89585c99b4daed164798f307244c9bde17b4f66014fbChris Forbes                return true;
89595c99b4daed164798f307244c9bde17b4f66014fbChris Forbes        }
89609ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski        // Validate pCreateInfo->imageArrayLayers against VkSurfaceCapabilitiesKHR::maxImageArrayLayers:
89615c99b4daed164798f307244c9bde17b4f66014fbChris Forbes        if ((pCreateInfo->imageArrayLayers < 1) || (pCreateInfo->imageArrayLayers > capabilities.maxImageArrayLayers)) {
89625c99b4daed164798f307244c9bde17b4f66014fbChris Forbes            if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
8963315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(dev_data->device), __LINE__, VALIDATION_ERROR_146009f6, "DS",
89649ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                        "%s called with a non-supported imageArrayLayers (i.e. %d).  Minimum value is 1, maximum value is %d. %s",
89659ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                        func_name, pCreateInfo->imageArrayLayers, capabilities.maxImageArrayLayers,
8966315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_146009f6]))
89675c99b4daed164798f307244c9bde17b4f66014fbChris Forbes                return true;
89685c99b4daed164798f307244c9bde17b4f66014fbChris Forbes        }
89699ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski        // Validate pCreateInfo->imageUsage against VkSurfaceCapabilitiesKHR::supportedUsageFlags:
89705c99b4daed164798f307244c9bde17b4f66014fbChris Forbes        if (pCreateInfo->imageUsage != (pCreateInfo->imageUsage & capabilities.supportedUsageFlags)) {
89715c99b4daed164798f307244c9bde17b4f66014fbChris Forbes            if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
8972315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(dev_data->device), __LINE__, VALIDATION_ERROR_146009f8, "DS",
89739ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                        "%s called with a non-supported pCreateInfo->imageUsage (i.e. 0x%08x).  Supported flag bits are 0x%08x. %s",
89749ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                        func_name, pCreateInfo->imageUsage, capabilities.supportedUsageFlags,
8975315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_146009f8]))
89765c99b4daed164798f307244c9bde17b4f66014fbChris Forbes                return true;
89775c99b4daed164798f307244c9bde17b4f66014fbChris Forbes        }
89787de258f87ca1192db116a66b209253793d276ebcChris Forbes    }
8979d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes
89809ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski    // Validate pCreateInfo values with the results of vkGetPhysicalDeviceSurfaceFormatsKHR():
89815faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes    if (physical_device_state->vkGetPhysicalDeviceSurfaceFormatsKHRState != QUERY_DETAILS) {
89825faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes        if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
89839b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                    HandleToUint64(dev_data->device), __LINE__, DRAWSTATE_SWAPCHAIN_CREATE_BEFORE_QUERY, "DS",
89849ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                    "%s called before calling vkGetPhysicalDeviceSurfaceFormatsKHR().", func_name))
89855faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes            return true;
89865faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes    } else {
89879ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski        // Validate pCreateInfo->imageFormat against VkSurfaceFormatKHR::format:
89885faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes        bool foundFormat = false;
89895faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes        bool foundColorSpace = false;
89905faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes        bool foundMatch = false;
89915faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes        for (auto const &format : physical_device_state->surface_formats) {
89925faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes            if (pCreateInfo->imageFormat == format.format) {
89939ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                // Validate pCreateInfo->imageColorSpace against VkSurfaceFormatKHR::colorSpace:
89945faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes                foundFormat = true;
89955faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes                if (pCreateInfo->imageColorSpace == format.colorSpace) {
89965faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes                    foundMatch = true;
89975faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes                    break;
89985faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes                }
89995faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes            } else {
90005faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes                if (pCreateInfo->imageColorSpace == format.colorSpace) {
90015faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes                    foundColorSpace = true;
90025faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes                }
90035faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes            }
90045faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes        }
90055faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes        if (!foundMatch) {
90065faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes            if (!foundFormat) {
90075faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes                if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
9008315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(dev_data->device), __LINE__, VALIDATION_ERROR_146009f2, "DS",
9009bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                            "%s called with a non-supported pCreateInfo->imageFormat (i.e. %d). %s", func_name,
9010315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            pCreateInfo->imageFormat, validation_error_map[VALIDATION_ERROR_146009f2]))
90112fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen                    return true;
90122fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen            }
90132fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen            if (!foundColorSpace) {
90142fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen                if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
9015315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(dev_data->device), __LINE__, VALIDATION_ERROR_146009f2, "DS",
9016bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                            "%s called with a non-supported pCreateInfo->imageColorSpace (i.e. %d). %s", func_name,
9017315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            pCreateInfo->imageColorSpace, validation_error_map[VALIDATION_ERROR_146009f2]))
90185faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes                    return true;
90195faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes            }
90205faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes        }
90215faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes    }
90225faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes
90239ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski    // Validate pCreateInfo values with the results of vkGetPhysicalDeviceSurfacePresentModesKHR():
90249e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes    if (physical_device_state->vkGetPhysicalDeviceSurfacePresentModesKHRState != QUERY_DETAILS) {
902525002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski        // FIFO is required to always be supported
90269e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes        if (pCreateInfo->presentMode != VK_PRESENT_MODE_FIFO_KHR) {
90279e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes            if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
90289b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        HandleToUint64(dev_data->device), __LINE__, DRAWSTATE_SWAPCHAIN_CREATE_BEFORE_QUERY, "DS",
90299ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                        "%s called before calling vkGetPhysicalDeviceSurfacePresentModesKHR().", func_name))
90309e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes                return true;
90319e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes        }
90329e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes    } else {
90339ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski        // Validate pCreateInfo->presentMode against vkGetPhysicalDeviceSurfacePresentModesKHR():
9034bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        bool foundMatch = std::find(physical_device_state->present_modes.begin(), physical_device_state->present_modes.end(),
90359e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes                                    pCreateInfo->presentMode) != physical_device_state->present_modes.end();
90369e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes        if (!foundMatch) {
90379e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes            if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
9038315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(dev_data->device), __LINE__, VALIDATION_ERROR_14600a02, "DS",
90399ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                        "%s called with a non-supported presentMode (i.e. %s). %s", func_name,
9040315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        string_VkPresentModeKHR(pCreateInfo->presentMode), validation_error_map[VALIDATION_ERROR_14600a02]))
90419e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes                return true;
90429e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes        }
90439e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes    }
904487a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis    // Validate state for shared presentable case
904587a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis    if (VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR == pCreateInfo->presentMode ||
904687a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis        VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR == pCreateInfo->presentMode) {
9047a149f1a0cb39b48b19822c8cf9ef2426cd2251dfMark Lobodzinski        if (!dev_data->extensions.vk_khr_shared_presentable_image) {
904887a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis            if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
9049480a11822ef9a45f577f13644759c0895a49db19Tobin Ehlis                        HandleToUint64(dev_data->device), __LINE__, DRAWSTATE_EXTENSION_NOT_ENABLED, "DS",
90506084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski                        "%s called with presentMode %s which requires the VK_KHR_shared_presentable_image extension, which has not "
90516084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski                        "been enabled.",
90526084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski                        func_name, string_VkPresentModeKHR(pCreateInfo->presentMode)))
90536084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski                return true;
90546084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski        } else if (pCreateInfo->minImageCount != 1) {
90556084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski            if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
9056315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        reinterpret_cast<uint64_t>(dev_data->device), __LINE__, VALIDATION_ERROR_14600ace, "DS",
905787a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis                        "%s called with presentMode %s, but minImageCount value is %d. For shared presentable image, minImageCount "
90586084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski                        "must be 1. %s",
90596084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski                        func_name, string_VkPresentModeKHR(pCreateInfo->presentMode), pCreateInfo->minImageCount,
9060315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_14600ace]))
906187a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis                return true;
906287a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis        }
906387a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis    }
90649e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes
9065d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes    return false;
9066d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes}
9067d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes
9068261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinskistatic void PostCallRecordCreateSwapchainKHR(layer_data *dev_data, VkResult result, const VkSwapchainCreateInfoKHR *pCreateInfo,
9069261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski                                             VkSwapchainKHR *pSwapchain, SURFACE_STATE *surface_state,
9070261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski                                             SWAPCHAIN_NODE *old_swapchain_state) {
90715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
9072ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes        lock_guard_t lock(global_lock);
9073ddc5201048319558ce66701163a4546ee957af19Chris Forbes        auto swapchain_state = unique_ptr<SWAPCHAIN_NODE>(new SWAPCHAIN_NODE(pCreateInfo, *pSwapchain));
907487a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis        if (VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR == pCreateInfo->presentMode ||
907587a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis            VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR == pCreateInfo->presentMode) {
907687a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis            swapchain_state->shared_presentable = true;
907787a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis        }
9078ddc5201048319558ce66701163a4546ee957af19Chris Forbes        surface_state->swapchain = swapchain_state.get();
907916a1f8f9c4af479b1873e82ff02360817fb658acChris Forbes        dev_data->swapchainMap[*pSwapchain] = std::move(swapchain_state);
9080ddc5201048319558ce66701163a4546ee957af19Chris Forbes    } else {
9081ddc5201048319558ce66701163a4546ee957af19Chris Forbes        surface_state->swapchain = nullptr;
90825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
9083ddc5201048319558ce66701163a4546ee957af19Chris Forbes    // Spec requires that even if CreateSwapchainKHR fails, oldSwapchain behaves as replaced.
90845b5488456e5afa0487f95b805a2aba59b13d69f4Chris Forbes    if (old_swapchain_state) {
90855b5488456e5afa0487f95b805a2aba59b13d69f4Chris Forbes        old_swapchain_state->replaced = true;
90865b5488456e5afa0487f95b805a2aba59b13d69f4Chris Forbes    }
9087ddc5201048319558ce66701163a4546ee957af19Chris Forbes    surface_state->old_swapchain = old_swapchain_state;
9088261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski    return;
9089261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski}
9090261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski
9091261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo,
9092261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski                                                  const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchain) {
909356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
90949a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto surface_state = GetSurfaceState(dev_data->instance_data, pCreateInfo->surface);
90959a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto old_swapchain_state = GetSwapchainNode(dev_data, pCreateInfo->oldSwapchain);
9096261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski
90979ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski    if (PreCallValidateCreateSwapchainKHR(dev_data, "vkCreateSwapChainKHR()", pCreateInfo, surface_state, old_swapchain_state)) {
9098261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski        return VK_ERROR_VALIDATION_FAILED_EXT;
9099261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski    }
9100261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski
9101261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski    VkResult result = dev_data->dispatch_table.CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain);
9102261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski
9103261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski    PostCallRecordCreateSwapchainKHR(dev_data, result, pCreateInfo, pSwapchain, surface_state, old_swapchain_state);
9104ddc5201048319558ce66701163a4546ee957af19Chris Forbes
91055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
91065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
91075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
9108bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks *pAllocator) {
910956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
91103251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
91115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
9112ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
91139a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto swapchain_data = GetSwapchainNode(dev_data, swapchain);
9114b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis    if (swapchain_data) {
9115b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis        if (swapchain_data->images.size() > 0) {
9116b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis            for (auto swapchain_image : swapchain_data->images) {
91175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                auto image_sub = dev_data->imageSubresourceMap.find(swapchain_image);
91185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                if (image_sub != dev_data->imageSubresourceMap.end()) {
91195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    for (auto imgsubpair : image_sub->second) {
91205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        auto image_item = dev_data->imageLayoutMap.find(imgsubpair);
91215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        if (image_item != dev_data->imageLayoutMap.end()) {
91225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                            dev_data->imageLayoutMap.erase(image_item);
91235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        }
91245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    }
91255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    dev_data->imageSubresourceMap.erase(image_sub);
91265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
91279b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                skip = ClearMemoryObjectBindings(dev_data, HandleToUint64(swapchain_image), kVulkanObjectTypeSwapchainKHR);
912894c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis                dev_data->imageMap.erase(swapchain_image);
91295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
91305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
9131ddc5201048319558ce66701163a4546ee957af19Chris Forbes
91329a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto surface_state = GetSurfaceState(dev_data->instance_data, swapchain_data->createInfo.surface);
9133ddc5201048319558ce66701163a4546ee957af19Chris Forbes        if (surface_state) {
9134cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            if (surface_state->swapchain == swapchain_data) surface_state->swapchain = nullptr;
9135cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            if (surface_state->old_swapchain == swapchain_data) surface_state->old_swapchain = nullptr;
9136ddc5201048319558ce66701163a4546ee957af19Chris Forbes        }
9137ddc5201048319558ce66701163a4546ee957af19Chris Forbes
913816a1f8f9c4af479b1873e82ff02360817fb658acChris Forbes        dev_data->swapchainMap.erase(swapchain);
91395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
9140b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
91413251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (!skip) dev_data->dispatch_table.DestroySwapchainKHR(device, swapchain, pAllocator);
91425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
91435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
9144991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinskistatic bool PreCallValidateGetSwapchainImagesKHR(layer_data *device_data, SWAPCHAIN_NODE *swapchain_state, VkDevice device,
9145991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                                                 uint32_t *pSwapchainImageCount, VkImage *pSwapchainImages) {
9146991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    bool skip = false;
9147991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    if (swapchain_state && pSwapchainImages) {
9148ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes        lock_guard_t lock(global_lock);
9149991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski        // Compare the preliminary value of *pSwapchainImageCount with the value this time:
9150991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski        if (swapchain_state->vkGetSwapchainImagesKHRState == UNCALLED) {
9151991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
9152991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                            HandleToUint64(device), __LINE__, SWAPCHAIN_PRIOR_COUNT, "DS",
9153991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                            "vkGetSwapchainImagesKHR() called with non-NULL pSwapchainImageCount; but no prior positive "
9154991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                            "value has been seen for pSwapchainImages.");
9155991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski        } else if (*pSwapchainImageCount > swapchain_state->get_swapchain_image_count) {
9156991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
9157991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                            HandleToUint64(device), __LINE__, SWAPCHAIN_INVALID_COUNT, "DS",
9158991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                            "vkGetSwapchainImagesKHR() called with non-NULL pSwapchainImageCount, and with "
9159991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                            "pSwapchainImages set to a value (%d) that is greater than the value (%d) that was returned when "
9160991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                            "pSwapchainImageCount was NULL.",
9161991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                            *pSwapchainImageCount, swapchain_state->get_swapchain_image_count);
9162991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski        }
9163991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    }
9164991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    return skip;
9165991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski}
9166991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski
9167991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinskistatic void PostCallRecordGetSwapchainImagesKHR(layer_data *device_data, SWAPCHAIN_NODE *swapchain_state, VkDevice device,
9168991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                                                uint32_t *pSwapchainImageCount, VkImage *pSwapchainImages) {
9169ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    lock_guard_t lock(global_lock);
9170ee52d734440f0770b3ac5ebde5a137d2e40589deChris Forbes
9171991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    if (*pSwapchainImageCount > swapchain_state->images.size()) swapchain_state->images.resize(*pSwapchainImageCount);
9172ee52d734440f0770b3ac5ebde5a137d2e40589deChris Forbes
9173991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    if (pSwapchainImages) {
9174991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski        if (swapchain_state->vkGetSwapchainImagesKHRState < QUERY_DETAILS) {
9175991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            swapchain_state->vkGetSwapchainImagesKHRState = QUERY_DETAILS;
9176991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski        }
9177991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski        for (uint32_t i = 0; i < *pSwapchainImageCount; ++i) {
9178991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            if (swapchain_state->images[i] != VK_NULL_HANDLE) continue;  // Already retrieved this.
9179ee52d734440f0770b3ac5ebde5a137d2e40589deChris Forbes
91805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            IMAGE_LAYOUT_NODE image_layout_node;
91815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            image_layout_node.layout = VK_IMAGE_LAYOUT_UNDEFINED;
9182991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            image_layout_node.format = swapchain_state->createInfo.imageFormat;
91836d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis            // Add imageMap entries for each swapchain image
91846d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis            VkImageCreateInfo image_ci = {};
9185eb6ea7587bdc06e98a89398f113fe3610d270dcbChris Forbes            image_ci.flags = 0;
9186eb6ea7587bdc06e98a89398f113fe3610d270dcbChris Forbes            image_ci.imageType = VK_IMAGE_TYPE_2D;
9187991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            image_ci.format = swapchain_state->createInfo.imageFormat;
9188991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            image_ci.extent.width = swapchain_state->createInfo.imageExtent.width;
9189991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            image_ci.extent.height = swapchain_state->createInfo.imageExtent.height;
9190d1a9776c1a22ec99a3ef0dd44e7f85a78a04d1edTony Barbour            image_ci.extent.depth = 1;
9191eb6ea7587bdc06e98a89398f113fe3610d270dcbChris Forbes            image_ci.mipLevels = 1;
9192991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            image_ci.arrayLayers = swapchain_state->createInfo.imageArrayLayers;
9193eb6ea7587bdc06e98a89398f113fe3610d270dcbChris Forbes            image_ci.samples = VK_SAMPLE_COUNT_1_BIT;
9194eb6ea7587bdc06e98a89398f113fe3610d270dcbChris Forbes            image_ci.tiling = VK_IMAGE_TILING_OPTIMAL;
9195991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            image_ci.usage = swapchain_state->createInfo.imageUsage;
9196991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            image_ci.sharingMode = swapchain_state->createInfo.imageSharingMode;
9197991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            device_data->imageMap[pSwapchainImages[i]] = unique_ptr<IMAGE_STATE>(new IMAGE_STATE(pSwapchainImages[i], &image_ci));
9198991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            auto &image_state = device_data->imageMap[pSwapchainImages[i]];
91991facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis            image_state->valid = false;
9200e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis            image_state->binding.mem = MEMTRACKER_SWAP_CHAIN_IMAGE_KEY;
9201991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            swapchain_state->images[i] = pSwapchainImages[i];
92025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            ImageSubresourcePair subpair = {pSwapchainImages[i], false, VkImageSubresource()};
9203991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            device_data->imageSubresourceMap[pSwapchainImages[i]].push_back(subpair);
9204991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            device_data->imageLayoutMap[subpair] = image_layout_node;
92055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
92065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
9207991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski
9208991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    if (*pSwapchainImageCount) {
9209991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski        if (swapchain_state->vkGetSwapchainImagesKHRState < QUERY_COUNT) {
9210991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            swapchain_state->vkGetSwapchainImagesKHRState = QUERY_COUNT;
9211991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski        }
9212991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski        swapchain_state->get_swapchain_image_count = *pSwapchainImageCount;
9213991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    }
9214991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski}
9215991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski
9216991f2555bc4f571e30b584937c7959805dff67c6Mark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL GetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t *pSwapchainImageCount,
9217991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                                                     VkImage *pSwapchainImages) {
9218991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
9219991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    layer_data *device_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
9220991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski
9221991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    auto swapchain_state = GetSwapchainNode(device_data, swapchain);
9222991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    bool skip = PreCallValidateGetSwapchainImagesKHR(device_data, swapchain_state, device, pSwapchainImageCount, pSwapchainImages);
9223991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski
9224991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    if (!skip) {
9225991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski        result = device_data->dispatch_table.GetSwapchainImagesKHR(device, swapchain, pSwapchainImageCount, pSwapchainImages);
9226991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    }
9227991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski
9228991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    if ((result == VK_SUCCESS || result == VK_INCOMPLETE)) {
9229991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski        PostCallRecordGetSwapchainImagesKHR(device_data, swapchain_state, device, pSwapchainImageCount, pSwapchainImages);
9230991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    }
92315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
92325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
92335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
923489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo) {
923556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map);
92363251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
92375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
9238ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    lock_guard_t lock(global_lock);
92399a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto queue_state = GetQueueState(dev_data, queue);
92401671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes
92416c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes    for (uint32_t i = 0; i < pPresentInfo->waitSemaphoreCount; ++i) {
92429a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto pSemaphore = GetSemaphoreNode(dev_data, pPresentInfo->pWaitSemaphores[i]);
92436c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes        if (pSemaphore && !pSemaphore->signaled) {
92443251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0,
92453251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS",
92463251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "Queue 0x%p is waiting on semaphore 0x%" PRIx64 " that has no way to be signaled.", queue,
92479b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(pPresentInfo->pWaitSemaphores[i]));
92485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
92496c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes    }
9250249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis
92516c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes    for (uint32_t i = 0; i < pPresentInfo->swapchainCount; ++i) {
92529a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto swapchain_data = GetSwapchainNode(dev_data, pPresentInfo->pSwapchains[i]);
9253a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes        if (swapchain_data) {
9254a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes            if (pPresentInfo->pImageIndices[i] >= swapchain_data->images.size()) {
92559b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                skip |=
92569b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
92579b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(pPresentInfo->pSwapchains[i]), __LINE__, DRAWSTATE_SWAPCHAIN_INVALID_IMAGE, "DS",
92589b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            "vkQueuePresentKHR: Swapchain image index too large (%u). There are only %u images in this swapchain.",
92599b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            pPresentInfo->pImageIndices[i], (uint32_t)swapchain_data->images.size());
9260bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski            } else {
9261a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes                auto image = swapchain_data->images[pPresentInfo->pImageIndices[i]];
92629a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                auto image_state = GetImageState(dev_data, image);
926387a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis
926487a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis                if (image_state->shared_presentable) {
926587a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis                    image_state->layout_locked = true;
926687a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis                }
9267c4f799ed5502f05ce97543e0500b4a19dc5f2461Mark Lobodzinski
92683251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= ValidateImageMemoryIsValid(dev_data, image_state, "vkQueuePresentKHR()");
9269a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes
92701facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis                if (!image_state->acquired) {
92713251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= log_msg(
9272bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                        dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
92739b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        HandleToUint64(pPresentInfo->pSwapchains[i]), __LINE__, DRAWSTATE_SWAPCHAIN_IMAGE_NOT_ACQUIRED, "DS",
9274bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                        "vkQueuePresentKHR: Swapchain image index %u has not been acquired.", pPresentInfo->pImageIndices[i]);
9275a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes                }
9276a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes
9277a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes                vector<VkImageLayout> layouts;
9278a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes                if (FindLayouts(dev_data, image, layouts)) {
9279a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes                    for (auto layout : layouts) {
92806084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski                        if ((layout != VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) &&
9281a149f1a0cb39b48b19822c8cf9ef2426cd2251dfMark Lobodzinski                            (!dev_data->extensions.vk_khr_shared_presentable_image ||
92826084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski                             (layout != VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR))) {
92833251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            skip |=
92842fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen                                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT,
9285315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                        HandleToUint64(queue), __LINE__, VALIDATION_ERROR_11200a20, "DS",
92862fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen                                        "Images passed to present must be in layout "
92876084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski                                        "VK_IMAGE_LAYOUT_PRESENT_SRC_KHR or VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR but is in %s. %s",
9288315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                        string_VkImageLayout(layout), validation_error_map[VALIDATION_ERROR_11200a20]);
9289a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes                        }
92905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    }
92915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
92925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
92931671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes
92941671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes            // All physical devices and queue families are required to be able
92951671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes            // to present to any native window on Android; require the
92961671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes            // application to have established support on any other platform.
9297d4eaca34eca7f4b4e34190c441a579347bb2016aMark Lobodzinski            if (!dev_data->instance_data->extensions.vk_khr_android_surface) {
92989a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                auto surface_state = GetSurfaceState(dev_data->instance_data, swapchain_data->createInfo.surface);
92991671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes                auto support_it = surface_state->gpu_queue_support.find({dev_data->physical_device, queue_state->queueFamilyIndex});
93001671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes
93011671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes                if (support_it == surface_state->gpu_queue_support.end()) {
93023251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |=
93031671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes                        log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
93049b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                HandleToUint64(pPresentInfo->pSwapchains[i]), __LINE__, DRAWSTATE_SWAPCHAIN_UNSUPPORTED_QUEUE, "DS",
9305cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                                "vkQueuePresentKHR: Presenting image without calling "
9306cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                                "vkGetPhysicalDeviceSurfaceSupportKHR");
93071671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes                } else if (!support_it->second) {
93089b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                    skip |=
93099b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
9310315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                HandleToUint64(pPresentInfo->pSwapchains[i]), __LINE__, VALIDATION_ERROR_31800a18, "DS",
93119b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                "vkQueuePresentKHR: Presenting image on queue that cannot "
93129b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                "present to this surface. %s",
9313315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                validation_error_map[VALIDATION_ERROR_31800a18]);
93141671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes                }
93151671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes            }
93165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
93175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
9318c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis    if (pPresentInfo && pPresentInfo->pNext) {
9319c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis        // Verify ext struct
9320c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis        struct std_header {
9321c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis            VkStructureType sType;
9322c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis            const void *pNext;
9323c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis        };
9324c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis        std_header *pnext = (std_header *)pPresentInfo->pNext;
9325c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis        while (pnext) {
9326c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis            if (VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR == pnext->sType) {
9327c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis                VkPresentRegionsKHR *present_regions = (VkPresentRegionsKHR *)pnext;
9328c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis                for (uint32_t i = 0; i < present_regions->swapchainCount; ++i) {
9329c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis                    auto swapchain_data = GetSwapchainNode(dev_data, pPresentInfo->pSwapchains[i]);
9330c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis                    assert(swapchain_data);
9331c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis                    VkPresentRegionKHR region = present_regions->pRegions[i];
9332c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis                    for (uint32_t j = 0; j < region.rectangleCount; ++j) {
9333c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis                        VkRectLayerKHR rect = region.pRectangles[j];
9334c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis                        // TODO: Need to update these errors to their unique error ids when available
9335c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis                        if ((rect.offset.x + rect.extent.width) > swapchain_data->createInfo.imageExtent.width) {
93369b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            skip |= log_msg(
93379b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
93389b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                HandleToUint64(pPresentInfo->pSwapchains[i]), __LINE__, DRAWSTATE_SWAPCHAIN_INVALID_IMAGE, "DS",
93399b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                "vkQueuePresentKHR(): For VkPresentRegionKHR down pNext "
93409b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                "chain, pRegion[%i].pRectangles[%i], the sum of offset.x "
93419b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                "(%i) and extent.width (%i) is greater than the "
93429b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                "corresponding swapchain's imageExtent.width (%i).",
93439b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                i, j, rect.offset.x, rect.extent.width, swapchain_data->createInfo.imageExtent.width);
9344c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis                        }
9345c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis                        if ((rect.offset.y + rect.extent.height) > swapchain_data->createInfo.imageExtent.height) {
93469b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            skip |= log_msg(
93479b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
93489b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                HandleToUint64(pPresentInfo->pSwapchains[i]), __LINE__, DRAWSTATE_SWAPCHAIN_INVALID_IMAGE, "DS",
93499b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                "vkQueuePresentKHR(): For VkPresentRegionKHR down pNext "
93509b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                "chain, pRegion[%i].pRectangles[%i], the sum of offset.y "
93519b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                "(%i) and extent.height (%i) is greater than the "
93529b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                "corresponding swapchain's imageExtent.height (%i).",
93539b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                i, j, rect.offset.y, rect.extent.height, swapchain_data->createInfo.imageExtent.height);
9354c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis                        }
9355c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis                        if (rect.layer > swapchain_data->createInfo.imageArrayLayers) {
93563251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            skip |= log_msg(
9357c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis                                dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
93589b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                HandleToUint64(pPresentInfo->pSwapchains[i]), __LINE__, DRAWSTATE_SWAPCHAIN_INVALID_IMAGE, "DS",
9359c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis                                "vkQueuePresentKHR(): For VkPresentRegionKHR down pNext chain, pRegion[%i].pRectangles[%i], the "
9360c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis                                "layer (%i) is greater than the corresponding swapchain's imageArrayLayers (%i).",
9361c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis                                i, j, rect.layer, swapchain_data->createInfo.imageArrayLayers);
9362c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis                        }
9363c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis                    }
9364c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis                }
93655f5e4095d630df9003597a928c86502e3fc83176Tobin Ehlis            } else if (VK_STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE == pnext->sType) {
93665f5e4095d630df9003597a928c86502e3fc83176Tobin Ehlis                VkPresentTimesInfoGOOGLE *present_times_info = (VkPresentTimesInfoGOOGLE *)pnext;
93675f5e4095d630df9003597a928c86502e3fc83176Tobin Ehlis                if (pPresentInfo->swapchainCount != present_times_info->swapchainCount) {
93685f5e4095d630df9003597a928c86502e3fc83176Tobin Ehlis                    skip |=
93695f5e4095d630df9003597a928c86502e3fc83176Tobin Ehlis                        log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
93709b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                HandleToUint64(pPresentInfo->pSwapchains[0]), __LINE__,
93715f5e4095d630df9003597a928c86502e3fc83176Tobin Ehlis
9372315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                VALIDATION_ERROR_118009be, "DS",
93735f5e4095d630df9003597a928c86502e3fc83176Tobin Ehlis                                "vkQueuePresentKHR(): VkPresentTimesInfoGOOGLE.swapchainCount is %i but "
93745f5e4095d630df9003597a928c86502e3fc83176Tobin Ehlis                                "pPresentInfo->swapchainCount is %i. For VkPresentTimesInfoGOOGLE down pNext "
93755f5e4095d630df9003597a928c86502e3fc83176Tobin Ehlis                                "chain of VkPresentInfoKHR, VkPresentTimesInfoGOOGLE.swapchainCount "
93765f5e4095d630df9003597a928c86502e3fc83176Tobin Ehlis                                "must equal VkPresentInfoKHR.swapchainCount.",
93775f5e4095d630df9003597a928c86502e3fc83176Tobin Ehlis                                present_times_info->swapchainCount, pPresentInfo->swapchainCount);
93785f5e4095d630df9003597a928c86502e3fc83176Tobin Ehlis                }
9379c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis            }
9380c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis            pnext = (std_header *)pnext->pNext;
9381c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis        }
9382c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis    }
93835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
93843251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (skip) {
93856c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes        return VK_ERROR_VALIDATION_FAILED_EXT;
93866c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes    }
93876c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes
93884a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.QueuePresentKHR(queue, pPresentInfo);
93896c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes
93906c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes    if (result != VK_ERROR_VALIDATION_FAILED_EXT) {
93916c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes        // Semaphore waits occur before error generation, if the call reached
93926c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes        // the ICD. (Confirm?)
93936c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes        for (uint32_t i = 0; i < pPresentInfo->waitSemaphoreCount; ++i) {
93949a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            auto pSemaphore = GetSemaphoreNode(dev_data, pPresentInfo->pWaitSemaphores[i]);
93959867daedbf52debc77d6568162ee21e071699b80Chris Forbes            if (pSemaphore) {
93969867daedbf52debc77d6568162ee21e071699b80Chris Forbes                pSemaphore->signaler.first = VK_NULL_HANDLE;
93976c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes                pSemaphore->signaled = false;
93986c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes            }
93996c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes        }
94009867daedbf52debc77d6568162ee21e071699b80Chris Forbes
9401220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes        for (uint32_t i = 0; i < pPresentInfo->swapchainCount; ++i) {
9402220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes            // Note: this is imperfect, in that we can get confused about what
9403220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes            // did or didn't succeed-- but if the app does that, it's confused
9404220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes            // itself just as much.
9405220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes            auto local_result = pPresentInfo->pResults ? pPresentInfo->pResults[i] : result;
9406220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes
9407cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            if (local_result != VK_SUCCESS && local_result != VK_SUBOPTIMAL_KHR) continue;  // this present didn't actually happen.
9408220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes
9409220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes            // Mark the image as having been released to the WSI
94109a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            auto swapchain_data = GetSwapchainNode(dev_data, pPresentInfo->pSwapchains[i]);
9411220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes            auto image = swapchain_data->images[pPresentInfo->pImageIndices[i]];
94129a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            auto image_state = GetImageState(dev_data, image);
94131facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis            image_state->acquired = false;
9414220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes        }
9415220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes
94169867daedbf52debc77d6568162ee21e071699b80Chris Forbes        // Note: even though presentation is directed to a queue, there is no
94179867daedbf52debc77d6568162ee21e071699b80Chris Forbes        // direct ordering between QP and subsequent work, so QP (and its
94189867daedbf52debc77d6568162ee21e071699b80Chris Forbes        // semaphore waits) /never/ participate in any completion proof.
94196c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes    }
94201344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis
94215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
94225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
94235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
9424c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinskistatic bool PreCallValidateCreateSharedSwapchainsKHR(layer_data *dev_data, uint32_t swapchainCount,
9425c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski                                                     const VkSwapchainCreateInfoKHR *pCreateInfos, VkSwapchainKHR *pSwapchains,
9426c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski                                                     std::vector<SURFACE_STATE *> &surface_state,
9427c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski                                                     std::vector<SWAPCHAIN_NODE *> &old_swapchain_state) {
94280342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski    if (pCreateInfos) {
9429ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes        lock_guard_t lock(global_lock);
94300342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski        for (uint32_t i = 0; i < swapchainCount; i++) {
94319a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            surface_state.push_back(GetSurfaceState(dev_data->instance_data, pCreateInfos[i].surface));
94329a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            old_swapchain_state.push_back(GetSwapchainNode(dev_data, pCreateInfos[i].oldSwapchain));
94339ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski            std::stringstream func_name;
94349ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski            func_name << "vkCreateSharedSwapchainsKHR[" << swapchainCount << "]";
9435bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski            if (PreCallValidateCreateSwapchainKHR(dev_data, func_name.str().c_str(), &pCreateInfos[i], surface_state[i],
9436bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                  old_swapchain_state[i])) {
9437c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski                return true;
94380342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski            }
94390342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski        }
94400342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski    }
9441c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski    return false;
9442c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski}
94430342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski
9444c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinskistatic void PostCallRecordCreateSharedSwapchainsKHR(layer_data *dev_data, VkResult result, uint32_t swapchainCount,
9445c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski                                                    const VkSwapchainCreateInfoKHR *pCreateInfos, VkSwapchainKHR *pSwapchains,
9446c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski                                                    std::vector<SURFACE_STATE *> &surface_state,
9447c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski                                                    std::vector<SWAPCHAIN_NODE *> &old_swapchain_state) {
94480342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski    if (VK_SUCCESS == result) {
94490342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski        for (uint32_t i = 0; i < swapchainCount; i++) {
94500342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski            auto swapchain_state = unique_ptr<SWAPCHAIN_NODE>(new SWAPCHAIN_NODE(&pCreateInfos[i], pSwapchains[i]));
945187a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis            if (VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR == pCreateInfos[i].presentMode ||
945287a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis                VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR == pCreateInfos[i].presentMode) {
945387a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis                swapchain_state->shared_presentable = true;
945487a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis            }
94550342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski            surface_state[i]->swapchain = swapchain_state.get();
945616a1f8f9c4af479b1873e82ff02360817fb658acChris Forbes            dev_data->swapchainMap[pSwapchains[i]] = std::move(swapchain_state);
94570342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski        }
94580342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski    } else {
94590342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski        for (uint32_t i = 0; i < swapchainCount; i++) {
94600342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski            surface_state[i]->swapchain = nullptr;
94610342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski        }
94620342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski    }
94630342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski    // Spec requires that even if CreateSharedSwapchainKHR fails, oldSwapchain behaves as replaced.
94640342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski    for (uint32_t i = 0; i < swapchainCount; i++) {
94650342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski        if (old_swapchain_state[i]) {
94660342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski            old_swapchain_state[i]->replaced = true;
94670342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski        }
94680342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski        surface_state[i]->old_swapchain = old_swapchain_state[i];
94690342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski    }
9470c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski    return;
9471c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski}
9472c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski
9473c6cd632d064579a64e61d8704b411d0e4ace7adaMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateSharedSwapchainsKHR(VkDevice device, uint32_t swapchainCount,
9474c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski                                                         const VkSwapchainCreateInfoKHR *pCreateInfos,
9475c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski                                                         const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchains) {
947656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
9477c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski    std::vector<SURFACE_STATE *> surface_state;
9478c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski    std::vector<SWAPCHAIN_NODE *> old_swapchain_state;
9479c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski
9480c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski    if (PreCallValidateCreateSharedSwapchainsKHR(dev_data, swapchainCount, pCreateInfos, pSwapchains, surface_state,
9481c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski                                                 old_swapchain_state)) {
9482c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski        return VK_ERROR_VALIDATION_FAILED_EXT;
9483c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski    }
9484c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski
9485c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski    VkResult result =
9486c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski        dev_data->dispatch_table.CreateSharedSwapchainsKHR(device, swapchainCount, pCreateInfos, pAllocator, pSwapchains);
9487c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski
9488c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski    PostCallRecordCreateSharedSwapchainsKHR(dev_data, result, swapchainCount, pCreateInfos, pSwapchains, surface_state,
9489c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski                                            old_swapchain_state);
94900342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski
9491c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young    return result;
9492c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young}
9493c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young
949489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL AcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout,
949589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                                   VkSemaphore semaphore, VkFence fence, uint32_t *pImageIndex) {
949656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
94973251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
94981344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis
9499ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
9500449670637ef4214b33018f497cf10daeff9dc85bChris Forbes
9501449670637ef4214b33018f497cf10daeff9dc85bChris Forbes    if (fence == VK_NULL_HANDLE && semaphore == VK_NULL_HANDLE) {
95023251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
95039b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        HandleToUint64(device), __LINE__, DRAWSTATE_SWAPCHAIN_NO_SYNC_FOR_ACQUIRE, "DS",
95043251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "vkAcquireNextImageKHR: Semaphore and fence cannot both be VK_NULL_HANDLE. There would be no way "
95053251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "to determine the completion of this operation.");
9506449670637ef4214b33018f497cf10daeff9dc85bChris Forbes    }
9507449670637ef4214b33018f497cf10daeff9dc85bChris Forbes
95089a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto pSemaphore = GetSemaphoreNode(dev_data, semaphore);
9509f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes    if (pSemaphore && pSemaphore->signaled) {
95103251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT,
9511315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(semaphore), __LINE__, VALIDATION_ERROR_16400a0c, "DS",
95123251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "vkAcquireNextImageKHR: Semaphore must not be currently signaled or in a wait state. %s",
9513315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_16400a0c]);
95145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
9515f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes
95169a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto pFence = GetFenceNode(dev_data, fence);
9517f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes    if (pFence) {
95183251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateFenceForSubmit(dev_data, pFence);
95195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
95204a5614452104c88cb04390dac882dd94ebdcc3deChris Forbes
95219a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto swapchain_data = GetSwapchainNode(dev_data, swapchain);
9522fc9f0448c3cb6ba4fc018fefe761bb43a1884846Chris Forbes
9523fc9f0448c3cb6ba4fc018fefe761bb43a1884846Chris Forbes    if (swapchain_data->replaced) {
95243251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
95259b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        HandleToUint64(swapchain), __LINE__, DRAWSTATE_SWAPCHAIN_REPLACED, "DS",
95263251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "vkAcquireNextImageKHR: This swapchain has been replaced. The application can still "
95273251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "present any images it has acquired, but cannot acquire any more.");
9528fc9f0448c3cb6ba4fc018fefe761bb43a1884846Chris Forbes    }
9529fc9f0448c3cb6ba4fc018fefe761bb43a1884846Chris Forbes
95309a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto physical_device_state = GetPhysicalDeviceState(dev_data->instance_data, dev_data->physical_device);
95314a5614452104c88cb04390dac882dd94ebdcc3deChris Forbes    if (physical_device_state->vkGetPhysicalDeviceSurfaceCapabilitiesKHRState != UNCALLED) {
95326569ab421f45f905e69fa7345bda4fe5b87e9045Mark Lobodzinski        uint64_t acquired_images = std::count_if(swapchain_data->images.begin(), swapchain_data->images.end(),
95339a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                                                 [=](VkImage image) { return GetImageState(dev_data, image)->acquired; });
95344a5614452104c88cb04390dac882dd94ebdcc3deChris Forbes        if (acquired_images > swapchain_data->images.size() - physical_device_state->surfaceCapabilities.minImageCount) {
95353251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |=
95366569ab421f45f905e69fa7345bda4fe5b87e9045Mark Lobodzinski                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
95379b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        HandleToUint64(swapchain), __LINE__, DRAWSTATE_SWAPCHAIN_TOO_MANY_IMAGES, "DS",
95386569ab421f45f905e69fa7345bda4fe5b87e9045Mark Lobodzinski                        "vkAcquireNextImageKHR: Application has already acquired the maximum number of images (0x%" PRIxLEAST64 ")",
95396569ab421f45f905e69fa7345bda4fe5b87e9045Mark Lobodzinski                        acquired_images);
95404a5614452104c88cb04390dac882dd94ebdcc3deChris Forbes        }
95414a5614452104c88cb04390dac882dd94ebdcc3deChris Forbes    }
954275269fc9e5cc9696ddf3dd28ff201c9b2526dc7aThomas Louis
954375269fc9e5cc9696ddf3dd28ff201c9b2526dc7aThomas Louis    if (swapchain_data->images.size() == 0) {
95443251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
95459b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        HandleToUint64(swapchain), __LINE__, DRAWSTATE_SWAPCHAIN_IMAGES_NOT_FOUND, "DS",
95463251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "vkAcquireNextImageKHR: No images found to acquire from. Application probably did not call "
95473251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "vkGetSwapchainImagesKHR after swapchain creation.");
954875269fc9e5cc9696ddf3dd28ff201c9b2526dc7aThomas Louis    }
954975269fc9e5cc9696ddf3dd28ff201c9b2526dc7aThomas Louis
9550b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
95511344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis
95523251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
9553f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes
95544a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.AcquireNextImageKHR(device, swapchain, timeout, semaphore, fence, pImageIndex);
9555f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes
9556f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes    lock.lock();
9557f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes    if (result == VK_SUCCESS || result == VK_SUBOPTIMAL_KHR) {
9558f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes        if (pFence) {
9559f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes            pFence->state = FENCE_INFLIGHT;
9560cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            pFence->signaler.first = VK_NULL_HANDLE;  // ANI isn't on a queue, so this can't participate in a completion proof.
9561f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes        }
9562f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes
9563f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes        // A successful call to AcquireNextImageKHR counts as a signal operation on semaphore
9564f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes        if (pSemaphore) {
9565f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes            pSemaphore->signaled = true;
95669867daedbf52debc77d6568162ee21e071699b80Chris Forbes            pSemaphore->signaler.first = VK_NULL_HANDLE;
9567f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes        }
9568220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes
9569220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes        // Mark the image as acquired.
9570220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes        auto image = swapchain_data->images[*pImageIndex];
95719a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto image_state = GetImageState(dev_data, image);
95721facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis        image_state->acquired = true;
957387a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis        image_state->shared_presentable = swapchain_data->shared_presentable;
95745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
9575f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes    lock.unlock();
95761344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis
95775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
95785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
95795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
9580f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL EnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount,
9581f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski                                                        VkPhysicalDevice *pPhysicalDevices) {
95823251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
958356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map);
9584bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis    assert(instance_data);
9585219f00ffed576643641976122fa1db8e5fce5dc1Chris Forbes
9586bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis    // For this instance, flag when vkEnumeratePhysicalDevices goes to QUERY_COUNT and then QUERY_DETAILS
9587bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis    if (NULL == pPhysicalDevices) {
9588bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis        instance_data->vkEnumeratePhysicalDevicesState = QUERY_COUNT;
9589f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski    } else {
9590bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis        if (UNCALLED == instance_data->vkEnumeratePhysicalDevicesState) {
9591bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis            // Flag warning here. You can call this without having queried the count, but it may not be
9592bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis            // robust on platforms with multiple physical devices.
95933251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
95943251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            0, __LINE__, DEVLIMITS_MISSING_QUERY_COUNT, "DL",
95953251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "Call sequence has vkEnumeratePhysicalDevices() w/ non-NULL pPhysicalDevices. You should first "
95963251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "call vkEnumeratePhysicalDevices() w/ NULL pPhysicalDevices to query pPhysicalDeviceCount.");
9597cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        }  // TODO : Could also flag a warning if re-calling this function in QUERY_DETAILS state
9598bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis        else if (instance_data->physical_devices_count != *pPhysicalDeviceCount) {
9599bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis            // Having actual count match count from app is not a requirement, so this can be a warning
96003251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT,
96013251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_COUNT_MISMATCH, "DL",
96023251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "Call to vkEnumeratePhysicalDevices() w/ pPhysicalDeviceCount value %u, but actual count "
96033251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "supported by this instance is %u.",
96043251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            *pPhysicalDeviceCount, instance_data->physical_devices_count);
9605bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis        }
9606bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis        instance_data->vkEnumeratePhysicalDevicesState = QUERY_DETAILS;
9607f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski    }
96083251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (skip) {
9609bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis        return VK_ERROR_VALIDATION_FAILED_EXT;
9610bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis    }
9611bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis    VkResult result = instance_data->dispatch_table.EnumeratePhysicalDevices(instance, pPhysicalDeviceCount, pPhysicalDevices);
9612bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis    if (NULL == pPhysicalDevices) {
9613bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis        instance_data->physical_devices_count = *pPhysicalDeviceCount;
9614cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    } else if (result == VK_SUCCESS) {  // Save physical devices
9615bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis        for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++) {
9616bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis            auto &phys_device_state = instance_data->physical_device_map[pPhysicalDevices[i]];
9617bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis            phys_device_state.phys_device = pPhysicalDevices[i];
9618bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis            // Init actual features for each physical device
9619bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis            instance_data->dispatch_table.GetPhysicalDeviceFeatures(pPhysicalDevices[i], &phys_device_state.features);
9620bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis        }
9621bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis    }
9622bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis    return result;
9623f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski}
9624f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski
962543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis// Common function to handle validation for GetPhysicalDeviceQueueFamilyProperties & 2KHR version
962643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic bool ValidateCommonGetPhysicalDeviceQueueFamilyProperties(instance_layer_data *instance_data,
962743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis                                                                 PHYSICAL_DEVICE_STATE *pd_state,
96285770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                                                                 uint32_t requested_queue_family_property_count, bool qfp_null,
96295770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                                                                 const char *caller_name) {
963043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis    bool skip = false;
96315770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    if (!qfp_null) {
96325770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus        // Verify that for each physical device, this command is called first with NULL pQueueFamilyProperties in order to get count
963343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis        if (UNCALLED == pd_state->vkGetPhysicalDeviceQueueFamilyPropertiesState) {
96345770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus            skip |= log_msg(
96355770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
96369b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                HandleToUint64(pd_state->phys_device), __LINE__, DEVLIMITS_MISSING_QUERY_COUNT, "DL",
96375770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                "%s is called with non-NULL pQueueFamilyProperties before obtaining pQueueFamilyPropertyCount. It is recommended "
96385770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                "to first call %s with NULL pQueueFamilyProperties in order to obtain the maximal pQueueFamilyPropertyCount.",
96395770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                caller_name, caller_name);
96405770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus            // Then verify that pCount that is passed in on second call matches what was returned
96415770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus        } else if (pd_state->queue_family_count != requested_queue_family_property_count) {
96425770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus            skip |= log_msg(
96435770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
96449b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                HandleToUint64(pd_state->phys_device), __LINE__, DEVLIMITS_COUNT_MISMATCH, "DL",
96455770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                "%s is called with non-NULL pQueueFamilyProperties and pQueueFamilyPropertyCount value %" PRIu32
96465770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                ", but the largest previously returned pQueueFamilyPropertyCount for this physicalDevice is %" PRIu32
96475770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                ". It is recommended to instead receive all the properties by calling %s with pQueueFamilyPropertyCount that was "
96485770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                "previously obtained by calling %s with NULL pQueueFamilyProperties.",
96495770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                caller_name, requested_queue_family_property_count, pd_state->queue_family_count, caller_name, caller_name);
965043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis        }
965143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis        pd_state->vkGetPhysicalDeviceQueueFamilyPropertiesState = QUERY_DETAILS;
965243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis    }
96535770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
965443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis    return skip;
965543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis}
965643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis
965743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic bool PreCallValidateGetPhysicalDeviceQueueFamilyProperties(instance_layer_data *instance_data,
96585770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                                                                  PHYSICAL_DEVICE_STATE *pd_state,
96595770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                                                                  uint32_t *pQueueFamilyPropertyCount,
966043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis                                                                  VkQueueFamilyProperties *pQueueFamilyProperties) {
96615770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    return ValidateCommonGetPhysicalDeviceQueueFamilyProperties(instance_data, pd_state, *pQueueFamilyPropertyCount,
96625770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                                                                (nullptr == pQueueFamilyProperties),
966343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis                                                                "vkGetPhysicalDeviceQueueFamilyProperties()");
966443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis}
966543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis
966643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic bool PreCallValidateGetPhysicalDeviceQueueFamilyProperties2KHR(instance_layer_data *instance_data,
966743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis                                                                      PHYSICAL_DEVICE_STATE *pd_state,
966843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis                                                                      uint32_t *pQueueFamilyPropertyCount,
966943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis                                                                      VkQueueFamilyProperties2KHR *pQueueFamilyProperties) {
96705770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    return ValidateCommonGetPhysicalDeviceQueueFamilyProperties(instance_data, pd_state, *pQueueFamilyPropertyCount,
96715770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                                                                (nullptr == pQueueFamilyProperties),
967243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis                                                                "vkGetPhysicalDeviceQueueFamilyProperties2KHR()");
967343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis}
967443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis
967543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis// Common function to update state for GetPhysicalDeviceQueueFamilyProperties & 2KHR version
967643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic void StateUpdateCommonGetPhysicalDeviceQueueFamilyProperties(PHYSICAL_DEVICE_STATE *pd_state, uint32_t count,
967743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis                                                                    VkQueueFamilyProperties2KHR *pQueueFamilyProperties) {
967843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis    if (!pQueueFamilyProperties) {
96795770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus        if (UNCALLED == pd_state->vkGetPhysicalDeviceQueueFamilyPropertiesState)
96805770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus            pd_state->vkGetPhysicalDeviceQueueFamilyPropertiesState = QUERY_COUNT;
96815770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus        pd_state->queue_family_count = count;
968243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis    } else {  // Save queue family properties
96835770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus        pd_state->vkGetPhysicalDeviceQueueFamilyPropertiesState = QUERY_DETAILS;
96845770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus        pd_state->queue_family_count = std::max(pd_state->queue_family_count, count);
96855770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
96865770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus        pd_state->queue_family_properties.resize(std::max(static_cast<uint32_t>(pd_state->queue_family_properties.size()), count));
96875770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus        for (uint32_t i = 0; i < count; ++i) {
968843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis            pd_state->queue_family_properties[i] = pQueueFamilyProperties[i].queueFamilyProperties;
968943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis        }
969043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis    }
969143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis}
969243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis
969343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic void PostCallRecordGetPhysicalDeviceQueueFamilyProperties(PHYSICAL_DEVICE_STATE *pd_state, uint32_t count,
969443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis                                                                 VkQueueFamilyProperties *pQueueFamilyProperties) {
969543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis    VkQueueFamilyProperties2KHR *pqfp = nullptr;
969643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis    std::vector<VkQueueFamilyProperties2KHR> qfp;
969743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis    qfp.resize(count);
969843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis    if (pQueueFamilyProperties) {
969943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis        for (uint32_t i = 0; i < count; ++i) {
970043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis            qfp[i].sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2_KHR;
970143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis            qfp[i].pNext = nullptr;
970243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis            qfp[i].queueFamilyProperties = pQueueFamilyProperties[i];
970343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis        }
970443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis        pqfp = qfp.data();
970543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis    }
970643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis    StateUpdateCommonGetPhysicalDeviceQueueFamilyProperties(pd_state, count, pqfp);
970743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis}
970843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis
970943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic void PostCallRecordGetPhysicalDeviceQueueFamilyProperties2KHR(PHYSICAL_DEVICE_STATE *pd_state, uint32_t count,
971043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis                                                                     VkQueueFamilyProperties2KHR *pQueueFamilyProperties) {
971143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis    StateUpdateCommonGetPhysicalDeviceQueueFamilyProperties(pd_state, count, pQueueFamilyProperties);
971243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis}
971343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis
97145770f8ad21c40b2475201e73e9368a899b6886d0Petr KrausVKAPI_ATTR void VKAPI_CALL GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice,
97155770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                                                                  uint32_t *pQueueFamilyPropertyCount,
9716bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                                  VkQueueFamilyProperties *pQueueFamilyProperties) {
971756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map);
97189a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto physical_device_state = GetPhysicalDeviceState(instance_data, physicalDevice);
971943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis    assert(physical_device_state);
9720ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
97215770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
97225770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    bool skip = PreCallValidateGetPhysicalDeviceQueueFamilyProperties(instance_data, physical_device_state,
97235770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                                                                      pQueueFamilyPropertyCount, pQueueFamilyProperties);
97245770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
97255770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    lock.unlock();
97265770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
97275770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    if (skip) return;
97285770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
97295770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    instance_data->dispatch_table.GetPhysicalDeviceQueueFamilyProperties(physicalDevice, pQueueFamilyPropertyCount,
97305770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                                                                         pQueueFamilyProperties);
97315770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
97325770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    lock.lock();
97335770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    PostCallRecordGetPhysicalDeviceQueueFamilyProperties(physical_device_state, *pQueueFamilyPropertyCount, pQueueFamilyProperties);
973443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis}
973543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis
973643947a6175e3e942e04d902f4d18928168e2d0dbTobin EhlisVKAPI_ATTR void VKAPI_CALL GetPhysicalDeviceQueueFamilyProperties2KHR(VkPhysicalDevice physicalDevice,
973743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis                                                                      uint32_t *pQueueFamilyPropertyCount,
973843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis                                                                      VkQueueFamilyProperties2KHR *pQueueFamilyProperties) {
973956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map);
97409a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto physical_device_state = GetPhysicalDeviceState(instance_data, physicalDevice);
974143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis    assert(physical_device_state);
9742ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
97435770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
974443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis    bool skip = PreCallValidateGetPhysicalDeviceQueueFamilyProperties2KHR(instance_data, physical_device_state,
974543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis                                                                          pQueueFamilyPropertyCount, pQueueFamilyProperties);
97465770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
97475770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    lock.unlock();
97485770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
97495770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    if (skip) return;
97505770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
975143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis    instance_data->dispatch_table.GetPhysicalDeviceQueueFamilyProperties2KHR(physicalDevice, pQueueFamilyPropertyCount,
975243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis                                                                             pQueueFamilyProperties);
97535770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
97545770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    lock.lock();
975543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis    PostCallRecordGetPhysicalDeviceQueueFamilyProperties2KHR(physical_device_state, *pQueueFamilyPropertyCount,
975643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis                                                             pQueueFamilyProperties);
9757cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski}
9758cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski
9759bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskitemplate <typename TCreateInfo, typename FPtr>
9760bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic VkResult CreateSurface(VkInstance instance, TCreateInfo const *pCreateInfo, VkAllocationCallbacks const *pAllocator,
9761bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                              VkSurfaceKHR *pSurface, FPtr fptr) {
976256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map);
9763747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
9764747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    // Call down the call chain:
9765747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    VkResult result = (instance_data->dispatch_table.*fptr)(instance, pCreateInfo, pAllocator, pSurface);
9766747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
9767747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    if (result == VK_SUCCESS) {
9768ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes        unique_lock_t lock(global_lock);
9769747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes        instance_data->surface_map[*pSurface] = SURFACE_STATE(*pSurface);
9770747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes        lock.unlock();
9771747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    }
9772747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
9773747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    return result;
9774747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes}
9775747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
9776747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR void VKAPI_CALL DestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks *pAllocator) {
97773251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
977856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map);
9779ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
97809a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto surface_state = GetSurfaceState(instance_data, surface);
9781747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
9782991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    if ((surface_state) && (surface_state->swapchain)) {
9783991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski        skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
9784991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            HandleToUint64(instance), __LINE__, VALIDATION_ERROR_26c009e4, "DS",
9785991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            "vkDestroySurfaceKHR() called before its associated VkSwapchainKHR was destroyed. %s",
9786991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            validation_error_map[VALIDATION_ERROR_26c009e4]);
9787747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    }
9788991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    instance_data->surface_map.erase(surface);
9789747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    lock.unlock();
97903251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (!skip) {
9791747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes        instance_data->dispatch_table.DestroySurfaceKHR(instance, surface, pAllocator);
9792747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    }
9793747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes}
9794747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
97956f2ed666809272002a31b3b4f8adf6581cb41819Norbert NopperVKAPI_ATTR VkResult VKAPI_CALL CreateDisplayPlaneSurfaceKHR(VkInstance instance, const VkDisplaySurfaceCreateInfoKHR *pCreateInfo,
97966f2ed666809272002a31b3b4f8adf6581cb41819Norbert Nopper                                                            const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
97976f2ed666809272002a31b3b4f8adf6581cb41819Norbert Nopper    return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateDisplayPlaneSurfaceKHR);
97986f2ed666809272002a31b3b4f8adf6581cb41819Norbert Nopper}
97996f2ed666809272002a31b3b4f8adf6581cb41819Norbert Nopper
9800747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_ANDROID_KHR
9801747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR *pCreateInfo,
9802747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes                                                       const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
9803747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateAndroidSurfaceKHR);
9804747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes}
9805cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif  // VK_USE_PLATFORM_ANDROID_KHR
9806747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
9807747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_MIR_KHR
9808747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateMirSurfaceKHR(VkInstance instance, const VkMirSurfaceCreateInfoKHR *pCreateInfo,
9809747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes                                                   const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
9810747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateMirSurfaceKHR);
9811747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes}
9812f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
9813f25d461667ca2db55147d2be49f179945edf24dbPetr KrausVKAPI_ATTR VkBool32 VKAPI_CALL GetPhysicalDeviceMirPresentationSupportKHR(VkPhysicalDevice physicalDevice,
9814f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus                                                                          uint32_t queueFamilyIndex, MirConnection *connection) {
9815f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    bool skip = false;
9816f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map);
9817f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
9818ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
9819f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    const auto pd_state = GetPhysicalDeviceState(instance_data, physicalDevice);
9820f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
9821315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis    skip |= ValidatePhysicalDeviceQueueFamily(instance_data, pd_state, queueFamilyIndex, VALIDATION_ERROR_2d2009e2,
9822f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus                                              "vkGetPhysicalDeviceMirPresentationSupportKHR", "queueFamilyIndex");
9823f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
9824f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    lock.unlock();
9825f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
9826f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    if (skip) return VK_FALSE;
9827f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
9828f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    // Call down the call chain:
9829f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    VkBool32 result =
9830f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus        instance_data->dispatch_table.GetPhysicalDeviceMirPresentationSupportKHR(physicalDevice, queueFamilyIndex, connection);
9831f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
9832f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    return result;
9833f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus}
9834cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif  // VK_USE_PLATFORM_MIR_KHR
9835747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
9836747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_WAYLAND_KHR
9837747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateWaylandSurfaceKHR(VkInstance instance, const VkWaylandSurfaceCreateInfoKHR *pCreateInfo,
9838747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes                                                       const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
9839a9c6cc532ce0ef61d48d1419a96aae51b0e4c64aTobin Ehlis    return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateWaylandSurfaceKHR);
9840747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes}
9841f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
9842f25d461667ca2db55147d2be49f179945edf24dbPetr KrausVKAPI_ATTR VkBool32 VKAPI_CALL GetPhysicalDeviceWaylandPresentationSupportKHR(VkPhysicalDevice physicalDevice,
9843f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus                                                                              uint32_t queueFamilyIndex,
9844f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus                                                                              struct wl_display *display) {
9845f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    bool skip = false;
9846f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map);
9847f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
9848ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
9849f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    const auto pd_state = GetPhysicalDeviceState(instance_data, physicalDevice);
9850f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
9851315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis    skip |= ValidatePhysicalDeviceQueueFamily(instance_data, pd_state, queueFamilyIndex, VALIDATION_ERROR_2f000a34,
9852f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus                                              "vkGetPhysicalDeviceWaylandPresentationSupportKHR", "queueFamilyIndex");
9853f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
9854f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    lock.unlock();
9855f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
9856f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    if (skip) return VK_FALSE;
9857f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
9858f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    // Call down the call chain:
9859f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    VkBool32 result =
9860f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus        instance_data->dispatch_table.GetPhysicalDeviceWaylandPresentationSupportKHR(physicalDevice, queueFamilyIndex, display);
9861f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
9862f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    return result;
9863f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus}
9864cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif  // VK_USE_PLATFORM_WAYLAND_KHR
9865747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
9866747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_WIN32_KHR
9867747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateWin32SurfaceKHR(VkInstance instance, const VkWin32SurfaceCreateInfoKHR *pCreateInfo,
9868747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes                                                     const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
9869747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateWin32SurfaceKHR);
9870747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes}
9871f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
9872f25d461667ca2db55147d2be49f179945edf24dbPetr KrausVKAPI_ATTR VkBool32 VKAPI_CALL GetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice physicalDevice,
9873f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus                                                                            uint32_t queueFamilyIndex) {
9874f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    bool skip = false;
9875f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map);
9876f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
9877ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
9878f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    const auto pd_state = GetPhysicalDeviceState(instance_data, physicalDevice);
9879f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
9880315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis    skip |= ValidatePhysicalDeviceQueueFamily(instance_data, pd_state, queueFamilyIndex, VALIDATION_ERROR_2f200a3a,
9881f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus                                              "vkGetPhysicalDeviceWin32PresentationSupportKHR", "queueFamilyIndex");
9882f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
9883f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    lock.unlock();
9884f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
9885f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    if (skip) return VK_FALSE;
9886f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
9887f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    // Call down the call chain:
9888f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    VkBool32 result = instance_data->dispatch_table.GetPhysicalDeviceWin32PresentationSupportKHR(physicalDevice, queueFamilyIndex);
9889f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
9890f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    return result;
9891f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus}
9892cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif  // VK_USE_PLATFORM_WIN32_KHR
9893747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
9894747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_XCB_KHR
9895747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateXcbSurfaceKHR(VkInstance instance, const VkXcbSurfaceCreateInfoKHR *pCreateInfo,
9896747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes                                                   const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
9897747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateXcbSurfaceKHR);
9898747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes}
9899f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
9900f25d461667ca2db55147d2be49f179945edf24dbPetr KrausVKAPI_ATTR VkBool32 VKAPI_CALL GetPhysicalDeviceXcbPresentationSupportKHR(VkPhysicalDevice physicalDevice,
9901f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus                                                                          uint32_t queueFamilyIndex, xcb_connection_t *connection,
9902f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus                                                                          xcb_visualid_t visual_id) {
9903f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    bool skip = false;
9904f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map);
9905f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
9906ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
9907f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    const auto pd_state = GetPhysicalDeviceState(instance_data, physicalDevice);
9908f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
9909315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis    skip |= ValidatePhysicalDeviceQueueFamily(instance_data, pd_state, queueFamilyIndex, VALIDATION_ERROR_2f400a40,
9910f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus                                              "vkGetPhysicalDeviceXcbPresentationSupportKHR", "queueFamilyIndex");
9911f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
9912f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    lock.unlock();
9913f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
9914f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    if (skip) return VK_FALSE;
9915f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
9916f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    // Call down the call chain:
9917f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    VkBool32 result = instance_data->dispatch_table.GetPhysicalDeviceXcbPresentationSupportKHR(physicalDevice, queueFamilyIndex,
9918f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus                                                                                               connection, visual_id);
9919f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
9920f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    return result;
9921f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus}
9922cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif  // VK_USE_PLATFORM_XCB_KHR
9923747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
9924747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_XLIB_KHR
9925747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateXlibSurfaceKHR(VkInstance instance, const VkXlibSurfaceCreateInfoKHR *pCreateInfo,
9926bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                    const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
9927747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateXlibSurfaceKHR);
9928747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes}
9929f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
9930f25d461667ca2db55147d2be49f179945edf24dbPetr KrausVKAPI_ATTR VkBool32 VKAPI_CALL GetPhysicalDeviceXlibPresentationSupportKHR(VkPhysicalDevice physicalDevice,
9931f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus                                                                           uint32_t queueFamilyIndex, Display *dpy,
9932f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus                                                                           VisualID visualID) {
9933f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    bool skip = false;
9934f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map);
9935f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
9936ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
9937f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    const auto pd_state = GetPhysicalDeviceState(instance_data, physicalDevice);
9938f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
9939315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis    skip |= ValidatePhysicalDeviceQueueFamily(instance_data, pd_state, queueFamilyIndex, VALIDATION_ERROR_2f600a46,
9940f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus                                              "vkGetPhysicalDeviceXlibPresentationSupportKHR", "queueFamilyIndex");
9941f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
9942f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    lock.unlock();
9943f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
9944f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    if (skip) return VK_FALSE;
9945f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
9946f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    // Call down the call chain:
9947f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    VkBool32 result =
9948f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus        instance_data->dispatch_table.GetPhysicalDeviceXlibPresentationSupportKHR(physicalDevice, queueFamilyIndex, dpy, visualID);
9949f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
9950f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    return result;
9951f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus}
9952cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif  // VK_USE_PLATFORM_XLIB_KHR
9953747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
995440921785005eb449ec7c18229f0d84c879708b8aChris ForbesVKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface,
995540921785005eb449ec7c18229f0d84c879708b8aChris Forbes                                                                       VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) {
995656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    auto instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map);
995740921785005eb449ec7c18229f0d84c879708b8aChris Forbes
9958ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
99599a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto physical_device_state = GetPhysicalDeviceState(instance_data, physicalDevice);
996040921785005eb449ec7c18229f0d84c879708b8aChris Forbes    lock.unlock();
996140921785005eb449ec7c18229f0d84c879708b8aChris Forbes
9962bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski    auto result =
9963bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        instance_data->dispatch_table.GetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, pSurfaceCapabilities);
996440921785005eb449ec7c18229f0d84c879708b8aChris Forbes
996540921785005eb449ec7c18229f0d84c879708b8aChris Forbes    if (result == VK_SUCCESS) {
996640921785005eb449ec7c18229f0d84c879708b8aChris Forbes        physical_device_state->vkGetPhysicalDeviceSurfaceCapabilitiesKHRState = QUERY_DETAILS;
996740921785005eb449ec7c18229f0d84c879708b8aChris Forbes        physical_device_state->surfaceCapabilities = *pSurfaceCapabilities;
996840921785005eb449ec7c18229f0d84c879708b8aChris Forbes    }
996940921785005eb449ec7c18229f0d84c879708b8aChris Forbes
997040921785005eb449ec7c18229f0d84c879708b8aChris Forbes    return result;
997140921785005eb449ec7c18229f0d84c879708b8aChris Forbes}
997240921785005eb449ec7c18229f0d84c879708b8aChris Forbes
997335b630211642e709485879a2e8859736f0ab16a0Mike Schuchardtstatic void PostCallRecordGetPhysicalDeviceSurfaceCapabilities2KHR(instance_layer_data *instanceData,
997435b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt                                                                   VkPhysicalDevice physicalDevice,
997535b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt                                                                   VkSurfaceCapabilities2KHR *pSurfaceCapabilities) {
9976ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
997735b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    auto physicalDeviceState = GetPhysicalDeviceState(instanceData, physicalDevice);
997835b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    physicalDeviceState->vkGetPhysicalDeviceSurfaceCapabilitiesKHRState = QUERY_DETAILS;
997935b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    physicalDeviceState->surfaceCapabilities = pSurfaceCapabilities->surfaceCapabilities;
998035b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt}
998135b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt
998235b630211642e709485879a2e8859736f0ab16a0Mike SchuchardtVKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice physicalDevice,
998335b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt                                                                        const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
998435b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt                                                                        VkSurfaceCapabilities2KHR *pSurfaceCapabilities) {
998535b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    auto instanceData = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map);
998635b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt
998735b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    auto result =
998835b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt        instanceData->dispatch_table.GetPhysicalDeviceSurfaceCapabilities2KHR(physicalDevice, pSurfaceInfo, pSurfaceCapabilities);
998935b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt
999035b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    if (result == VK_SUCCESS) {
999135b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt        PostCallRecordGetPhysicalDeviceSurfaceCapabilities2KHR(instanceData, physicalDevice, pSurfaceCapabilities);
999235b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    }
999335b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt
999435b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    return result;
999535b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt}
999635b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt
999735b630211642e709485879a2e8859736f0ab16a0Mike Schuchardtstatic void PostCallRecordGetPhysicalDeviceSurfaceCapabilities2EXT(instance_layer_data *instanceData,
999835b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt                                                                   VkPhysicalDevice physicalDevice,
999935b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt                                                                   VkSurfaceCapabilities2EXT *pSurfaceCapabilities) {
10000ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
1000135b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    auto physicalDeviceState = GetPhysicalDeviceState(instanceData, physicalDevice);
1000235b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    physicalDeviceState->vkGetPhysicalDeviceSurfaceCapabilitiesKHRState = QUERY_DETAILS;
1000335b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    physicalDeviceState->surfaceCapabilities.minImageCount = pSurfaceCapabilities->minImageCount;
1000435b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    physicalDeviceState->surfaceCapabilities.maxImageCount = pSurfaceCapabilities->maxImageCount;
1000535b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    physicalDeviceState->surfaceCapabilities.currentExtent = pSurfaceCapabilities->currentExtent;
1000635b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    physicalDeviceState->surfaceCapabilities.minImageExtent = pSurfaceCapabilities->minImageExtent;
1000735b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    physicalDeviceState->surfaceCapabilities.maxImageExtent = pSurfaceCapabilities->maxImageExtent;
1000835b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    physicalDeviceState->surfaceCapabilities.maxImageArrayLayers = pSurfaceCapabilities->maxImageArrayLayers;
1000935b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    physicalDeviceState->surfaceCapabilities.supportedTransforms = pSurfaceCapabilities->supportedTransforms;
1001035b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    physicalDeviceState->surfaceCapabilities.currentTransform = pSurfaceCapabilities->currentTransform;
1001135b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    physicalDeviceState->surfaceCapabilities.supportedCompositeAlpha = pSurfaceCapabilities->supportedCompositeAlpha;
1001235b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    physicalDeviceState->surfaceCapabilities.supportedUsageFlags = pSurfaceCapabilities->supportedUsageFlags;
1001335b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt}
1001435b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt
1001535b630211642e709485879a2e8859736f0ab16a0Mike SchuchardtVKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceCapabilities2EXT(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface,
1001635b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt                                                                        VkSurfaceCapabilities2EXT *pSurfaceCapabilities) {
1001735b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    auto instanceData = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map);
1001835b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt
1001935b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    auto result =
1002035b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt        instanceData->dispatch_table.GetPhysicalDeviceSurfaceCapabilities2EXT(physicalDevice, surface, pSurfaceCapabilities);
1002135b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt
1002235b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    if (result == VK_SUCCESS) {
1002335b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt        PostCallRecordGetPhysicalDeviceSurfaceCapabilities2EXT(instanceData, physicalDevice, pSurfaceCapabilities);
1002435b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    }
1002535b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt
1002635b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    return result;
1002735b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt}
1002835b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt
10029418a8711f3301f3027a900bb45daaf0892f4e644Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex,
10030418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes                                                                  VkSurfaceKHR surface, VkBool32 *pSupported) {
10031f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    bool skip = false;
1003256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    auto instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map);
10033f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
10034ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
10035f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    const auto pd_state = GetPhysicalDeviceState(instance_data, physicalDevice);
100369a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto surface_state = GetSurfaceState(instance_data, surface);
10037f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
10038315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis    skip |= ValidatePhysicalDeviceQueueFamily(instance_data, pd_state, queueFamilyIndex, VALIDATION_ERROR_2ee009ea,
10039f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus                                              "vkGetPhysicalDeviceSurfaceSupportKHR", "queueFamilyIndex");
10040f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
10041418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes    lock.unlock();
10042418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes
10043f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
10044f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
10045bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski    auto result =
10046bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        instance_data->dispatch_table.GetPhysicalDeviceSurfaceSupportKHR(physicalDevice, queueFamilyIndex, surface, pSupported);
10047418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes
10048418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes    if (result == VK_SUCCESS) {
100490bbc015828bdb99e85e6731ce92428557902701fPetr Kraus        surface_state->gpu_queue_support[{physicalDevice, queueFamilyIndex}] = (*pSupported == VK_TRUE);
10050418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes    }
10051418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes
10052418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes    return result;
10053418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes}
10054418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes
100559e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface,
100569e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes                                                                       uint32_t *pPresentModeCount,
100579e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes                                                                       VkPresentModeKHR *pPresentModes) {
100583251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
1005956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    auto instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map);
10060ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
100619e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes    // TODO: this isn't quite right. available modes may differ by surface AND physical device.
100629a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto physical_device_state = GetPhysicalDeviceState(instance_data, physicalDevice);
10063bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski    auto &call_state = physical_device_state->vkGetPhysicalDeviceSurfacePresentModesKHRState;
100649e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes
100659e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes    if (pPresentModes) {
100669e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes        // Compare the preliminary value of *pPresentModeCount with the value this time:
10067bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        auto prev_mode_count = (uint32_t)physical_device_state->present_modes.size();
100689e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes        switch (call_state) {
10069cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            case UNCALLED:
100703251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(
10071bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                    instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
100729b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                    HandleToUint64(physicalDevice), __LINE__, DEVLIMITS_MUST_QUERY_COUNT, "DL",
10073cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                    "vkGetPhysicalDeviceSurfacePresentModesKHR() called with non-NULL pPresentModeCount; but no prior positive "
10074cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                    "value has been seen for pPresentModeCount.");
10075cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                break;
10076cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            default:
10077cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                // both query count and query details
10078cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                if (*pPresentModeCount != prev_mode_count) {
100793251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT,
100809b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                    VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, HandleToUint64(physicalDevice), __LINE__,
100819b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                    DEVLIMITS_COUNT_MISMATCH, "DL",
100823251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    "vkGetPhysicalDeviceSurfacePresentModesKHR() called with *pPresentModeCount (%u) that "
100833251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    "differs from the value "
100843251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    "(%u) that was returned when pPresentModes was NULL.",
100853251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    *pPresentModeCount, prev_mode_count);
10086cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                }
10087cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                break;
100889e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes        }
100899e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes    }
100909e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes    lock.unlock();
100919e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes
100923251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
100939e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes
10094bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski    auto result = instance_data->dispatch_table.GetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, pPresentModeCount,
10095bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                                                        pPresentModes);
100969e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes
100979e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes    if (result == VK_SUCCESS || result == VK_INCOMPLETE) {
100989e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes        lock.lock();
100999e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes
101009e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes        if (*pPresentModeCount) {
10101cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            if (call_state < QUERY_COUNT) call_state = QUERY_COUNT;
101029e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes            if (*pPresentModeCount > physical_device_state->present_modes.size())
101039e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes                physical_device_state->present_modes.resize(*pPresentModeCount);
101049e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes        }
101059e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes        if (pPresentModes) {
10106cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            if (call_state < QUERY_DETAILS) call_state = QUERY_DETAILS;
101079e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes            for (uint32_t i = 0; i < *pPresentModeCount; i++) {
101089e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes                physical_device_state->present_modes[i] = pPresentModes[i];
101099e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes            }
101109e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes        }
101115faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes    }
101125faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes
101135faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes    return result;
101145faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes}
101155faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes
101165faa662f6859b01c72d79027abde363d5f10dcd7Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface,
101175faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes                                                                  uint32_t *pSurfaceFormatCount,
101185faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes                                                                  VkSurfaceFormatKHR *pSurfaceFormats) {
101193251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
1012056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    auto instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map);
10121ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
101229a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto physical_device_state = GetPhysicalDeviceState(instance_data, physicalDevice);
10123bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski    auto &call_state = physical_device_state->vkGetPhysicalDeviceSurfaceFormatsKHRState;
101245faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes
101255faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes    if (pSurfaceFormats) {
10126bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        auto prev_format_count = (uint32_t)physical_device_state->surface_formats.size();
101275faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes
101285faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes        switch (call_state) {
10129cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            case UNCALLED:
10130cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                // Since we haven't recorded a preliminary value of *pSurfaceFormatCount, that likely means that the application
10131cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                // didn't
10132cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                // previously call this function with a NULL value of pSurfaceFormats:
101333251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(
10134bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                    instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
101359b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                    HandleToUint64(physicalDevice), __LINE__, DEVLIMITS_MUST_QUERY_COUNT, "DL",
10136cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                    "vkGetPhysicalDeviceSurfaceFormatsKHR() called with non-NULL pSurfaceFormatCount; but no prior positive "
10137cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                    "value has been seen for pSurfaceFormats.");
10138cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                break;
10139cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            default:
10140cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                if (prev_format_count != *pSurfaceFormatCount) {
101413251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= log_msg(
10142cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                        instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT,
101439b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, HandleToUint64(physicalDevice), __LINE__,
10144cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                        DEVLIMITS_COUNT_MISMATCH, "DL",
10145cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                        "vkGetPhysicalDeviceSurfaceFormatsKHR() called with non-NULL pSurfaceFormatCount, and with pSurfaceFormats "
10146cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                        "set "
10147cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                        "to "
10148cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                        "a value (%u) that is greater than the value (%u) that was returned when pSurfaceFormatCount was NULL.",
10149cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                        *pSurfaceFormatCount, prev_format_count);
10150cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                }
10151cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                break;
101529e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes        }
101539e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes    }
101545faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes    lock.unlock();
101555faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes
101563251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
101579e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes
101585faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes    // Call down the call chain:
101595faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes    auto result = instance_data->dispatch_table.GetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, pSurfaceFormatCount,
101605faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes                                                                                   pSurfaceFormats);
101615faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes
101625faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes    if (result == VK_SUCCESS || result == VK_INCOMPLETE) {
101635faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes        lock.lock();
101645faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes
101655faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes        if (*pSurfaceFormatCount) {
10166cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            if (call_state < QUERY_COUNT) call_state = QUERY_COUNT;
101675faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes            if (*pSurfaceFormatCount > physical_device_state->surface_formats.size())
101685faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes                physical_device_state->surface_formats.resize(*pSurfaceFormatCount);
101695faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes        }
101705faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes        if (pSurfaceFormats) {
10171cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            if (call_state < QUERY_DETAILS) call_state = QUERY_DETAILS;
101725faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes            for (uint32_t i = 0; i < *pSurfaceFormatCount; i++) {
101735faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes                physical_device_state->surface_formats[i] = pSurfaceFormats[i];
101745faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes            }
101755faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes        }
101765faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes    }
101779e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes    return result;
101789e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes}
101799e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes
1018035b630211642e709485879a2e8859736f0ab16a0Mike Schuchardtstatic void PostCallRecordGetPhysicalDeviceSurfaceFormats2KHR(instance_layer_data *instanceData, VkPhysicalDevice physicalDevice,
1018135b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt                                                              uint32_t *pSurfaceFormatCount, VkSurfaceFormat2KHR *pSurfaceFormats) {
10182ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
1018335b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    auto physicalDeviceState = GetPhysicalDeviceState(instanceData, physicalDevice);
1018435b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    if (*pSurfaceFormatCount) {
1018535b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt        if (physicalDeviceState->vkGetPhysicalDeviceSurfaceFormatsKHRState < QUERY_COUNT) {
1018635b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt            physicalDeviceState->vkGetPhysicalDeviceSurfaceFormatsKHRState = QUERY_COUNT;
1018735b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt        }
1018835b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt        if (*pSurfaceFormatCount > physicalDeviceState->surface_formats.size())
1018935b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt            physicalDeviceState->surface_formats.resize(*pSurfaceFormatCount);
1019035b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    }
1019135b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    if (pSurfaceFormats) {
1019235b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt        if (physicalDeviceState->vkGetPhysicalDeviceSurfaceFormatsKHRState < QUERY_DETAILS) {
1019335b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt            physicalDeviceState->vkGetPhysicalDeviceSurfaceFormatsKHRState = QUERY_DETAILS;
1019435b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt        }
1019535b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt        for (uint32_t i = 0; i < *pSurfaceFormatCount; i++) {
1019635b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt            physicalDeviceState->surface_formats[i] = pSurfaceFormats[i].surfaceFormat;
1019735b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt        }
1019835b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    }
1019935b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt}
1020035b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt
1020135b630211642e709485879a2e8859736f0ab16a0Mike SchuchardtVKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceFormats2KHR(VkPhysicalDevice physicalDevice,
1020235b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt                                                                   const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
1020335b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt                                                                   uint32_t *pSurfaceFormatCount,
1020435b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt                                                                   VkSurfaceFormat2KHR *pSurfaceFormats) {
1020535b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    auto instanceData = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map);
1020635b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    auto result = instanceData->dispatch_table.GetPhysicalDeviceSurfaceFormats2KHR(physicalDevice, pSurfaceInfo,
1020735b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt                                                                                   pSurfaceFormatCount, pSurfaceFormats);
1020835b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    if (result == VK_SUCCESS || result == VK_INCOMPLETE) {
1020935b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt        PostCallRecordGetPhysicalDeviceSurfaceFormats2KHR(instanceData, physicalDevice, pSurfaceFormatCount, pSurfaceFormats);
1021035b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    }
1021135b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    return result;
1021235b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt}
1021335b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt
10214bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateDebugReportCallbackEXT(VkInstance instance,
10215bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                            const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
10216bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                            const VkAllocationCallbacks *pAllocator,
10217bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                            VkDebugReportCallbackEXT *pMsgCallback) {
1021856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map);
102199172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes    VkResult res = instance_data->dispatch_table.CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
102205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == res) {
10221ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes        lock_guard_t lock(global_lock);
102228860b85a52096f9f9b28616bc37feed505497a54Chris Forbes        res = layer_create_msg_callback(instance_data->report_data, false, pCreateInfo, pAllocator, pMsgCallback);
102235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
102245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return res;
102255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
102265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
10227bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT msgCallback,
1022889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                                         const VkAllocationCallbacks *pAllocator) {
1022956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map);
102309172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes    instance_data->dispatch_table.DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
10231ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    lock_guard_t lock(global_lock);
102328860b85a52096f9f9b28616bc37feed505497a54Chris Forbes    layer_destroy_msg_callback(instance_data->report_data, msgCallback, pAllocator);
102335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
102345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
10235bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags,
10236bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                 VkDebugReportObjectTypeEXT objType, uint64_t object, size_t location,
10237bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                 int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
1023856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map);
102399172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes    instance_data->dispatch_table.DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
102405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
102415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
10242bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
10243a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu    return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
10244a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu}
10245a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu
10246bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
10247bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                              VkLayerProperties *pProperties) {
10248a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu    return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
10249a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu}
10250a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu
10251bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
10252bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                                    VkExtensionProperties *pProperties) {
10253a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu    if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
10254a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu        return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
10255a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu
10256a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu    return VK_ERROR_LAYER_NOT_PRESENT;
10257a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu}
10258a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu
10259bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
10260bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                                  uint32_t *pCount, VkExtensionProperties *pProperties) {
10261cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(0, NULL, pCount, pProperties);
10262a8f4a23b1e9c068717eda47cc583a93f447c77e3Chia-I Wu
10263a8f4a23b1e9c068717eda47cc583a93f447c77e3Chia-I Wu    assert(physicalDevice);
10264a8f4a23b1e9c068717eda47cc583a93f447c77e3Chia-I Wu
1026556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map);
102669172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes    return instance_data->dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
1026708939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu}
1026808939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu
10269582b6ed09649188d55ed3b6237352caf9f3384a9Mike WeiblenVKAPI_ATTR VkResult VKAPI_CALL EnumeratePhysicalDeviceGroupsKHX(
10270582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen    VkInstance instance, uint32_t *pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupPropertiesKHX *pPhysicalDeviceGroupProperties) {
102713251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
10272582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen    instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map);
10273582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen
10274582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen    if (instance_data) {
10275582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen        // For this instance, flag when EnumeratePhysicalDeviceGroupsKHX goes to QUERY_COUNT and then QUERY_DETAILS.
10276582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen        if (NULL == pPhysicalDeviceGroupProperties) {
10277582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen            instance_data->vkEnumeratePhysicalDeviceGroupsState = QUERY_COUNT;
10278582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen        } else {
10279582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen            if (UNCALLED == instance_data->vkEnumeratePhysicalDeviceGroupsState) {
10280582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen                // Flag warning here. You can call this without having queried the count, but it may not be
10281582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen                // robust on platforms with multiple physical devices.
102823251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT,
102833251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, 0, __LINE__, DEVLIMITS_MISSING_QUERY_COUNT, "DL",
102843251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "Call sequence has vkEnumeratePhysicalDeviceGroupsKHX() w/ non-NULL "
102853251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "pPhysicalDeviceGroupProperties. You should first "
102863251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "call vkEnumeratePhysicalDeviceGroupsKHX() w/ NULL pPhysicalDeviceGroupProperties to query "
102873251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "pPhysicalDeviceGroupCount.");
10288582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen            } // TODO : Could also flag a warning if re-calling this function in QUERY_DETAILS state
10289582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen            else if (instance_data->physical_device_groups_count != *pPhysicalDeviceGroupCount) {
10290582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen                // Having actual count match count from app is not a requirement, so this can be a warning
102913251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |=
10292582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen                    log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT,
102933251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_COUNT_MISMATCH, "DL",
102943251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "Call to vkEnumeratePhysicalDeviceGroupsKHX() w/ pPhysicalDeviceGroupCount value %u, but actual count "
102953251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "supported by this instance is %u.",
102963251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            *pPhysicalDeviceGroupCount, instance_data->physical_device_groups_count);
10297582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen            }
10298582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen            instance_data->vkEnumeratePhysicalDeviceGroupsState = QUERY_DETAILS;
10299582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen        }
103003251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        if (skip) {
10301582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen            return VK_ERROR_VALIDATION_FAILED_EXT;
10302582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen        }
10303582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen        VkResult result = instance_data->dispatch_table.EnumeratePhysicalDeviceGroupsKHX(instance, pPhysicalDeviceGroupCount,
10304582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen            pPhysicalDeviceGroupProperties);
10305582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen        if (NULL == pPhysicalDeviceGroupProperties) {
10306582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen            instance_data->physical_device_groups_count = *pPhysicalDeviceGroupCount;
10307582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen        } else if (result == VK_SUCCESS) { // Save physical devices
10308582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen            for (uint32_t i = 0; i < *pPhysicalDeviceGroupCount; i++) {
10309582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen                for (uint32_t j = 0; j < pPhysicalDeviceGroupProperties[i].physicalDeviceCount; j++) {
10310582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen                    VkPhysicalDevice cur_phys_dev = pPhysicalDeviceGroupProperties[i].physicalDevices[j];
10311582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen                    auto &phys_device_state = instance_data->physical_device_map[cur_phys_dev];
10312582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen                    phys_device_state.phys_device = cur_phys_dev;
10313582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen                    // Init actual features for each physical device
10314582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen                    instance_data->dispatch_table.GetPhysicalDeviceFeatures(cur_phys_dev, &phys_device_state.features);
10315582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen                }
10316582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen            }
10317582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen        }
10318582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen        return result;
10319582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen    } else {
10320582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen        log_msg(instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, 0, __LINE__,
103219b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                DEVLIMITS_INVALID_INSTANCE, "DL",
103229b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                "Invalid instance (0x%" PRIxLEAST64 ") passed into vkEnumeratePhysicalDeviceGroupsKHX().",
103239b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                HandleToUint64(instance));
10324582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen    }
10325582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen    return VK_ERROR_VALIDATION_FAILED_EXT;
10326582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen}
10327582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen
103286246f8feba03ddc787c31b3daa6a50d4ef01024fMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateDescriptorUpdateTemplateKHR(VkDevice device,
103296246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski                                                                 const VkDescriptorUpdateTemplateCreateInfoKHR *pCreateInfo,
103306246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski                                                                 const VkAllocationCallbacks *pAllocator,
103316246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski                                                                 VkDescriptorUpdateTemplateKHR *pDescriptorUpdateTemplate) {
103326246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
10333a538cd4fff983b172362b0bba58f984124481a1cMark Lobodzinski    VkResult result =
10334a538cd4fff983b172362b0bba58f984124481a1cMark Lobodzinski        dev_data->dispatch_table.CreateDescriptorUpdateTemplateKHR(device, pCreateInfo, pAllocator, pDescriptorUpdateTemplate);
103356246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski    if (VK_SUCCESS == result) {
10336ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes        lock_guard_t lock(global_lock);
103376246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski        // Shadow template createInfo for later updates
10338a538cd4fff983b172362b0bba58f984124481a1cMark Lobodzinski        safe_VkDescriptorUpdateTemplateCreateInfoKHR *local_create_info =
10339a538cd4fff983b172362b0bba58f984124481a1cMark Lobodzinski            new safe_VkDescriptorUpdateTemplateCreateInfoKHR(pCreateInfo);
103406246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski        std::unique_ptr<TEMPLATE_STATE> template_state(new TEMPLATE_STATE(*pDescriptorUpdateTemplate, local_create_info));
103416246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski        dev_data->desc_template_map[*pDescriptorUpdateTemplate] = std::move(template_state);
103426246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski    }
103436246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski    return result;
103446246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski}
103456246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski
103466246f8feba03ddc787c31b3daa6a50d4ef01024fMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyDescriptorUpdateTemplateKHR(VkDevice device,
103476246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski                                                              VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate,
103486246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski                                                              const VkAllocationCallbacks *pAllocator) {
103496246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
10350ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
103516246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski    dev_data->desc_template_map.erase(descriptorUpdateTemplate);
103526246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski    lock.unlock();
103536246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski    dev_data->dispatch_table.DestroyDescriptorUpdateTemplateKHR(device, descriptorUpdateTemplate, pAllocator);
103546246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski}
103556246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski
1035625f3712aed1cebdcb7c92eb25c5f1cc6e5986ac4Mark Lobodzinski// PostCallRecord* handles recording state updates following call down chain to UpdateDescriptorSetsWithTemplate()
1035725f3712aed1cebdcb7c92eb25c5f1cc6e5986ac4Mark Lobodzinskistatic void PostCallRecordUpdateDescriptorSetWithTemplateKHR(layer_data *device_data, VkDescriptorSet descriptorSet,
1035825f3712aed1cebdcb7c92eb25c5f1cc6e5986ac4Mark Lobodzinski                                                             VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate,
1035925f3712aed1cebdcb7c92eb25c5f1cc6e5986ac4Mark Lobodzinski                                                             const void *pData) {
1036067fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski    auto const template_map_entry = device_data->desc_template_map.find(descriptorUpdateTemplate);
1036167fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski    if (template_map_entry == device_data->desc_template_map.end()) {
1036267fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski        assert(0);
1036367fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski    }
1036467fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski
1036525f3712aed1cebdcb7c92eb25c5f1cc6e5986ac4Mark Lobodzinski    cvdescriptorset::PerformUpdateDescriptorSetsWithTemplateKHR(device_data, descriptorSet, template_map_entry->second, pData);
1036667fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski}
1036767fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski
103686246f8feba03ddc787c31b3daa6a50d4ef01024fMark LobodzinskiVKAPI_ATTR void VKAPI_CALL UpdateDescriptorSetWithTemplateKHR(VkDevice device, VkDescriptorSet descriptorSet,
103696246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski                                                              VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate,
103706246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski                                                              const void *pData) {
1037167fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski    layer_data *device_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1037267fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski    device_data->dispatch_table.UpdateDescriptorSetWithTemplateKHR(device, descriptorSet, descriptorUpdateTemplate, pData);
1037367fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski
1037467fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski    PostCallRecordUpdateDescriptorSetWithTemplateKHR(device_data, descriptorSet, descriptorUpdateTemplate, pData);
103756246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski}
103766246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski
103776246f8feba03ddc787c31b3daa6a50d4ef01024fMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdPushDescriptorSetWithTemplateKHR(VkCommandBuffer commandBuffer,
103786246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski                                                               VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate,
103796246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski                                                               VkPipelineLayout layout, uint32_t set, const void *pData) {
103806246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
103816246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski    dev_data->dispatch_table.CmdPushDescriptorSetWithTemplateKHR(commandBuffer, descriptorUpdateTemplate, layout, set, pData);
103826246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski}
103836246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski
10384991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinskistatic void PostCallRecordGetPhysicalDeviceDisplayPlanePropertiesKHR(instance_layer_data *instanceData,
10385991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                                                                     VkPhysicalDevice physicalDevice, uint32_t *pPropertyCount,
10386991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                                                                     VkDisplayPlanePropertiesKHR *pProperties) {
10387ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
10388991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    auto physical_device_state = GetPhysicalDeviceState(instanceData, physicalDevice);
10389991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski
10390991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    if (*pPropertyCount) {
103917c9b2aea1e047762ea9cff97ddd1fd33b5efc71dChris Forbes        if (physical_device_state->vkGetPhysicalDeviceDisplayPlanePropertiesKHRState < QUERY_COUNT) {
103927c9b2aea1e047762ea9cff97ddd1fd33b5efc71dChris Forbes            physical_device_state->vkGetPhysicalDeviceDisplayPlanePropertiesKHRState = QUERY_COUNT;
10393991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski        }
10394991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski        physical_device_state->display_plane_property_count = *pPropertyCount;
10395991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    }
10396991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    if (pProperties) {
103977c9b2aea1e047762ea9cff97ddd1fd33b5efc71dChris Forbes        if (physical_device_state->vkGetPhysicalDeviceDisplayPlanePropertiesKHRState < QUERY_DETAILS) {
103987c9b2aea1e047762ea9cff97ddd1fd33b5efc71dChris Forbes            physical_device_state->vkGetPhysicalDeviceDisplayPlanePropertiesKHRState = QUERY_DETAILS;
10399991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski        }
10400991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    }
10401991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski}
10402991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski
10403991f2555bc4f571e30b584937c7959805dff67c6Mark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceDisplayPlanePropertiesKHR(VkPhysicalDevice physicalDevice, uint32_t *pPropertyCount,
10404991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                                                                          VkDisplayPlanePropertiesKHR *pProperties) {
10405991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    VkResult result = VK_SUCCESS;
10406991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map);
10407991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski
10408991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    result = instance_data->dispatch_table.GetPhysicalDeviceDisplayPlanePropertiesKHR(physicalDevice, pPropertyCount, pProperties);
10409991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski
10410991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    if (result == VK_SUCCESS || result == VK_INCOMPLETE) {
10411991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski        PostCallRecordGetPhysicalDeviceDisplayPlanePropertiesKHR(instance_data, physicalDevice, pPropertyCount, pProperties);
10412991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    }
10413991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski
10414991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    return result;
10415991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski}
10416991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski
10417991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinskistatic bool ValidateGetPhysicalDeviceDisplayPlanePropertiesKHRQuery(instance_layer_data *instance_data,
10418991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                                                                    VkPhysicalDevice physicalDevice, uint32_t planeIndex,
10419991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                                                                    const char *api_name) {
10420991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    bool skip = false;
10421991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    auto physical_device_state = GetPhysicalDeviceState(instance_data, physicalDevice);
104227c9b2aea1e047762ea9cff97ddd1fd33b5efc71dChris Forbes    if (physical_device_state->vkGetPhysicalDeviceDisplayPlanePropertiesKHRState == UNCALLED) {
10423991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski        skip |= log_msg(
10424991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
10425991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            HandleToUint64(physicalDevice), __LINE__, SWAPCHAIN_GET_SUPPORTED_DISPLAYS_WITHOUT_QUERY, "DL",
10426991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            "Potential problem with calling %s() without first querying vkGetPhysicalDeviceDisplayPlanePropertiesKHR.", api_name);
10427991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    } else {
10428991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski        if (planeIndex >= physical_device_state->display_plane_property_count) {
10429991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            skip |= log_msg(
10430991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
10431991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                HandleToUint64(physicalDevice), __LINE__, VALIDATION_ERROR_29c009c2, "DL",
10432991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                "%s(): planeIndex must be in the range [0, %d] that was returned by vkGetPhysicalDeviceDisplayPlanePropertiesKHR. "
10433991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                "Do you have the plane index hardcoded? %s",
10434991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                api_name, physical_device_state->display_plane_property_count - 1, validation_error_map[VALIDATION_ERROR_29c009c2]);
10435991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski        }
10436991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    }
10437991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    return skip;
10438991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski}
10439991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski
10440991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinskistatic bool PreCallValidateGetDisplayPlaneSupportedDisplaysKHR(instance_layer_data *instance_data, VkPhysicalDevice physicalDevice,
10441991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                                                               uint32_t planeIndex) {
10442991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    bool skip = false;
10443ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    lock_guard_t lock(global_lock);
10444991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    skip |= ValidateGetPhysicalDeviceDisplayPlanePropertiesKHRQuery(instance_data, physicalDevice, planeIndex,
10445991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                                                                    "vkGetDisplayPlaneSupportedDisplaysKHR");
10446991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    return skip;
10447991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski}
10448991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski
10449991f2555bc4f571e30b584937c7959805dff67c6Mark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL GetDisplayPlaneSupportedDisplaysKHR(VkPhysicalDevice physicalDevice, uint32_t planeIndex,
10450991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                                                                   uint32_t *pDisplayCount, VkDisplayKHR *pDisplays) {
10451991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
10452991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map);
10453991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    bool skip = PreCallValidateGetDisplayPlaneSupportedDisplaysKHR(instance_data, physicalDevice, planeIndex);
10454991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    if (!skip) {
10455991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski        result =
10456991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            instance_data->dispatch_table.GetDisplayPlaneSupportedDisplaysKHR(physicalDevice, planeIndex, pDisplayCount, pDisplays);
10457991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    }
10458991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    return result;
10459991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski}
10460991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski
10461991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinskistatic bool PreCallValidateGetDisplayPlaneCapabilitiesKHR(instance_layer_data *instance_data, VkPhysicalDevice physicalDevice,
10462991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                                                          uint32_t planeIndex) {
10463991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    bool skip = false;
10464ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    lock_guard_t lock(global_lock);
10465991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    skip |= ValidateGetPhysicalDeviceDisplayPlanePropertiesKHRQuery(instance_data, physicalDevice, planeIndex,
10466991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                                                                    "vkGetDisplayPlaneCapabilitiesKHR");
10467991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    return skip;
10468991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski}
10469991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski
10470991f2555bc4f571e30b584937c7959805dff67c6Mark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL GetDisplayPlaneCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkDisplayModeKHR mode,
10471991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                                                              uint32_t planeIndex, VkDisplayPlaneCapabilitiesKHR *pCapabilities) {
10472991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
10473991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map);
10474991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    bool skip = PreCallValidateGetDisplayPlaneCapabilitiesKHR(instance_data, physicalDevice, planeIndex);
10475991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski
10476991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    if (!skip) {
10477991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski        result = instance_data->dispatch_table.GetDisplayPlaneCapabilitiesKHR(physicalDevice, mode, planeIndex, pCapabilities);
10478991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    }
10479991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski
10480991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    return result;
10481991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski}
10482991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski
104836dd9a6bc380bc606441fb036974f0ddadff4d0c8Mark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL DebugMarkerSetObjectNameEXT(VkDevice device, const VkDebugMarkerObjectNameInfoEXT *pNameInfo) {
104841f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour    std::unique_lock<std::mutex> lock(global_lock);
104851f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour    layer_data *device_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
104861f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour    if (pNameInfo->pObjectName) {
104871f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour        device_data->report_data->debugObjectNameMap->insert(
104881f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour            std::make_pair<uint64_t, std::string>((uint64_t &&)pNameInfo->object, pNameInfo->pObjectName));
104891f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour    } else {
104901f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour        device_data->report_data->debugObjectNameMap->erase(pNameInfo->object);
104911f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour    }
104921f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour    lock.unlock();
104931f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour    VkResult result = device_data->dispatch_table.DebugMarkerSetObjectNameEXT(device, pNameInfo);
104941f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour    return result;
104951f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour}
104961f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour
104971f53907e108555555ac7cc8e0daf639279ca67d4Tony BarbourVKAPI_ATTR VkResult VKAPI_CALL DebugMarkerSetObjectTagEXT(VkDevice device, VkDebugMarkerObjectTagInfoEXT *pTagInfo) {
104981f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour    layer_data *device_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
104991f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour    VkResult result = device_data->dispatch_table.DebugMarkerSetObjectTagEXT(device, pTagInfo);
105001f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour    return result;
105011f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour}
105021f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour
105031f53907e108555555ac7cc8e0daf639279ca67d4Tony BarbourVKAPI_ATTR void VKAPI_CALL CmdDebugMarkerBeginEXT(VkCommandBuffer commandBuffer, VkDebugMarkerMarkerInfoEXT *pMarkerInfo) {
105041f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour    layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
105051f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour    device_data->dispatch_table.CmdDebugMarkerBeginEXT(commandBuffer, pMarkerInfo);
105061f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour}
105071f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour
105081f53907e108555555ac7cc8e0daf639279ca67d4Tony BarbourVKAPI_ATTR void VKAPI_CALL CmdDebugMarkerEndEXT(VkCommandBuffer commandBuffer) {
105091f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour    layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
105101f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour    device_data->dispatch_table.CmdDebugMarkerEndEXT(commandBuffer);
105111f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour}
105121f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour
105131f53907e108555555ac7cc8e0daf639279ca67d4Tony BarbourVKAPI_ATTR void VKAPI_CALL CmdDebugMarkerInsertEXT(VkCommandBuffer commandBuffer, VkDebugMarkerMarkerInfoEXT *pMarkerInfo) {
105141f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour    layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
105151f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour    device_data->dispatch_table.CmdDebugMarkerInsertEXT(commandBuffer, pMarkerInfo);
105161f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour}
105171f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour
105183616276bb0053c612c0a8d223e81ae3808b1b2c4Mark LobodzinskiVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName);
105193616276bb0053c612c0a8d223e81ae3808b1b2c4Mark LobodzinskiVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetPhysicalDeviceProcAddr(VkInstance instance, const char *funcName);
105203616276bb0053c612c0a8d223e81ae3808b1b2c4Mark LobodzinskiVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName);
105213616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski
105223616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski// Map of all APIs to be intercepted by this layer
105233616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinskistatic const std::unordered_map<std::string, void*> name_to_funcptr_map = {
105243616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetInstanceProcAddr", (void*)GetInstanceProcAddr},
105253616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vk_layerGetPhysicalDeviceProcAddr", (void*)GetPhysicalDeviceProcAddr},
105263616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetDeviceProcAddr", (void*)GetDeviceProcAddr},
105273616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateInstance", (void*)CreateInstance},
105283616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateDevice", (void*)CreateDevice},
105293616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkEnumeratePhysicalDevices", (void*)EnumeratePhysicalDevices},
105303616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetPhysicalDeviceQueueFamilyProperties", (void*)GetPhysicalDeviceQueueFamilyProperties},
105313616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroyInstance", (void*)DestroyInstance},
105323616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkEnumerateInstanceLayerProperties", (void*)EnumerateInstanceLayerProperties},
105333616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkEnumerateDeviceLayerProperties", (void*)EnumerateDeviceLayerProperties},
105343616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkEnumerateInstanceExtensionProperties", (void*)EnumerateInstanceExtensionProperties},
105353616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkEnumerateDeviceExtensionProperties", (void*)EnumerateDeviceExtensionProperties},
105363616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateDescriptorUpdateTemplateKHR", (void*)CreateDescriptorUpdateTemplateKHR},
105373616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroyDescriptorUpdateTemplateKHR", (void*)DestroyDescriptorUpdateTemplateKHR},
105383616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkUpdateDescriptorSetWithTemplateKHR", (void*)UpdateDescriptorSetWithTemplateKHR},
105393616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdPushDescriptorSetWithTemplateKHR", (void*)CmdPushDescriptorSetWithTemplateKHR},
105403616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateSwapchainKHR", (void*)CreateSwapchainKHR},
105413616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroySwapchainKHR", (void*)DestroySwapchainKHR},
105423616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetSwapchainImagesKHR", (void*)GetSwapchainImagesKHR},
105433616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkAcquireNextImageKHR", (void*)AcquireNextImageKHR},
105443616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkQueuePresentKHR", (void*)QueuePresentKHR},
105453616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkQueueSubmit", (void*)QueueSubmit},
105463616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkWaitForFences", (void*)WaitForFences},
105473616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetFenceStatus", (void*)GetFenceStatus},
105483616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkQueueWaitIdle", (void*)QueueWaitIdle},
105493616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDeviceWaitIdle", (void*)DeviceWaitIdle},
105503616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetDeviceQueue", (void*)GetDeviceQueue},
105513616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroyDevice", (void*)DestroyDevice},
105523616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroyFence", (void*)DestroyFence},
105533616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkResetFences", (void*)ResetFences},
105543616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroySemaphore", (void*)DestroySemaphore},
105553616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroyEvent", (void*)DestroyEvent},
105563616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroyQueryPool", (void*)DestroyQueryPool},
105573616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroyBuffer", (void*)DestroyBuffer},
105583616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroyBufferView", (void*)DestroyBufferView},
105593616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroyImage", (void*)DestroyImage},
105603616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroyImageView", (void*)DestroyImageView},
105613616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroyShaderModule", (void*)DestroyShaderModule},
105623616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroyPipeline", (void*)DestroyPipeline},
105633616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroyPipelineLayout", (void*)DestroyPipelineLayout},
105643616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroySampler", (void*)DestroySampler},
105653616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroyDescriptorSetLayout", (void*)DestroyDescriptorSetLayout},
105663616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroyDescriptorPool", (void*)DestroyDescriptorPool},
105673616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroyFramebuffer", (void*)DestroyFramebuffer},
105683616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroyRenderPass", (void*)DestroyRenderPass},
105693616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateBuffer", (void*)CreateBuffer},
105703616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateBufferView", (void*)CreateBufferView},
105713616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateImage", (void*)CreateImage},
105723616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateImageView", (void*)CreateImageView},
105733616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateFence", (void*)CreateFence},
105743616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreatePipelineCache", (void*)CreatePipelineCache},
105753616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroyPipelineCache", (void*)DestroyPipelineCache},
105763616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetPipelineCacheData", (void*)GetPipelineCacheData},
105773616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkMergePipelineCaches", (void*)MergePipelineCaches},
105783616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateGraphicsPipelines", (void*)CreateGraphicsPipelines},
105793616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateComputePipelines", (void*)CreateComputePipelines},
105803616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateSampler", (void*)CreateSampler},
105813616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateDescriptorSetLayout", (void*)CreateDescriptorSetLayout},
105823616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreatePipelineLayout", (void*)CreatePipelineLayout},
105833616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateDescriptorPool", (void*)CreateDescriptorPool},
105843616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkResetDescriptorPool", (void*)ResetDescriptorPool},
105853616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkAllocateDescriptorSets", (void*)AllocateDescriptorSets},
105863616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkFreeDescriptorSets", (void*)FreeDescriptorSets},
105873616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkUpdateDescriptorSets", (void*)UpdateDescriptorSets},
105883616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateCommandPool", (void*)CreateCommandPool},
105893616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroyCommandPool", (void*)DestroyCommandPool},
105903616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkResetCommandPool", (void*)ResetCommandPool},
105913616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateQueryPool", (void*)CreateQueryPool},
105923616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkAllocateCommandBuffers", (void*)AllocateCommandBuffers},
105933616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkFreeCommandBuffers", (void*)FreeCommandBuffers},
105943616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkBeginCommandBuffer", (void*)BeginCommandBuffer},
105953616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkEndCommandBuffer", (void*)EndCommandBuffer},
105963616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkResetCommandBuffer", (void*)ResetCommandBuffer},
105973616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdBindPipeline", (void*)CmdBindPipeline},
105983616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdSetViewport", (void*)CmdSetViewport},
105993616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdSetScissor", (void*)CmdSetScissor},
106003616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdSetLineWidth", (void*)CmdSetLineWidth},
106013616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdSetDepthBias", (void*)CmdSetDepthBias},
106023616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdSetBlendConstants", (void*)CmdSetBlendConstants},
106033616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdSetDepthBounds", (void*)CmdSetDepthBounds},
106043616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdSetStencilCompareMask", (void*)CmdSetStencilCompareMask},
106053616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdSetStencilWriteMask", (void*)CmdSetStencilWriteMask},
106063616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdSetStencilReference", (void*)CmdSetStencilReference},
106073616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdBindDescriptorSets", (void*)CmdBindDescriptorSets},
106083616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdBindVertexBuffers", (void*)CmdBindVertexBuffers},
106093616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdBindIndexBuffer", (void*)CmdBindIndexBuffer},
106103616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdDraw", (void*)CmdDraw},
106113616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdDrawIndexed", (void*)CmdDrawIndexed},
106123616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdDrawIndirect", (void*)CmdDrawIndirect},
106133616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdDrawIndexedIndirect", (void*)CmdDrawIndexedIndirect},
106143616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdDispatch", (void*)CmdDispatch},
106153616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdDispatchIndirect", (void*)CmdDispatchIndirect},
106163616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdCopyBuffer", (void*)CmdCopyBuffer},
106173616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdCopyImage", (void*)CmdCopyImage},
106183616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdBlitImage", (void*)CmdBlitImage},
106193616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdCopyBufferToImage", (void*)CmdCopyBufferToImage},
106203616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdCopyImageToBuffer", (void*)CmdCopyImageToBuffer},
106213616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdUpdateBuffer", (void*)CmdUpdateBuffer},
106223616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdFillBuffer", (void*)CmdFillBuffer},
106233616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdClearColorImage", (void*)CmdClearColorImage},
106243616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdClearDepthStencilImage", (void*)CmdClearDepthStencilImage},
106253616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdClearAttachments", (void*)CmdClearAttachments},
106263616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdResolveImage", (void*)CmdResolveImage},
106273616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetImageSubresourceLayout", (void*)GetImageSubresourceLayout},
106283616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdSetEvent", (void*)CmdSetEvent},
106293616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdResetEvent", (void*)CmdResetEvent},
106303616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdWaitEvents", (void*)CmdWaitEvents},
106313616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdPipelineBarrier", (void*)CmdPipelineBarrier},
106323616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdBeginQuery", (void*)CmdBeginQuery},
106333616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdEndQuery", (void*)CmdEndQuery},
106343616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdResetQueryPool", (void*)CmdResetQueryPool},
106353616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdCopyQueryPoolResults", (void*)CmdCopyQueryPoolResults},
106363616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdPushConstants", (void*)CmdPushConstants},
106373616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdWriteTimestamp", (void*)CmdWriteTimestamp},
106383616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateFramebuffer", (void*)CreateFramebuffer},
106393616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateShaderModule", (void*)CreateShaderModule},
106403616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateRenderPass", (void*)CreateRenderPass},
106413616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdBeginRenderPass", (void*)CmdBeginRenderPass},
106423616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdNextSubpass", (void*)CmdNextSubpass},
106433616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdEndRenderPass", (void*)CmdEndRenderPass},
106443616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdExecuteCommands", (void*)CmdExecuteCommands},
106451f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour    {"vkCmdDebugMarkerBeginEXT", (void*)CmdDebugMarkerBeginEXT},
106461f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour    {"vkCmdDebugMarkerEndEXT", (void*)CmdDebugMarkerEndEXT},
106471f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour    {"vkCmdDebugMarkerInsertEXT", (void*)CmdDebugMarkerInsertEXT},
106481f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour    {"vkDebugMarkerSetObjectNameEXT", (void*)DebugMarkerSetObjectNameEXT},
106491f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour    {"vkDebugMarkerSetObjectTagEXT", (void*)DebugMarkerSetObjectTagEXT},
106503616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkSetEvent", (void*)SetEvent},
106513616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkMapMemory", (void*)MapMemory},
106523616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkUnmapMemory", (void*)UnmapMemory},
106533616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkFlushMappedMemoryRanges", (void*)FlushMappedMemoryRanges},
106543616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkInvalidateMappedMemoryRanges", (void*)InvalidateMappedMemoryRanges},
106553616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkAllocateMemory", (void*)AllocateMemory},
106563616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkFreeMemory", (void*)FreeMemory},
106573616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkBindBufferMemory", (void*)BindBufferMemory},
106583616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetBufferMemoryRequirements", (void*)GetBufferMemoryRequirements},
106593616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetImageMemoryRequirements", (void*)GetImageMemoryRequirements},
106603616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetQueryPoolResults", (void*)GetQueryPoolResults},
106613616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkBindImageMemory", (void*)BindImageMemory},
106623616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkQueueBindSparse", (void*)QueueBindSparse},
106633616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateSemaphore", (void*)CreateSemaphore},
106643616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateEvent", (void*)CreateEvent},
106653616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski#ifdef VK_USE_PLATFORM_ANDROID_KHR
106663616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateAndroidSurfaceKHR", (void*)CreateAndroidSurfaceKHR},
106673616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski#endif
106683616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski#ifdef VK_USE_PLATFORM_MIR_KHR
106693616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateMirSurfaceKHR", (void*)CreateMirSurfaceKHR},
106703616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetPhysicalDeviceMirPresentationSupportKHR", (void*)GetPhysicalDeviceMirPresentationSupportKHR},
106713616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski#endif
106723616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski#ifdef VK_USE_PLATFORM_WAYLAND_KHR
106733616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateWaylandSurfaceKHR", (void*)CreateWaylandSurfaceKHR},
106743616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetPhysicalDeviceWaylandPresentationSupportKHR", (void*)GetPhysicalDeviceWaylandPresentationSupportKHR},
106753616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski#endif
106763616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski#ifdef VK_USE_PLATFORM_WIN32_KHR
106773616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateWin32SurfaceKHR", (void*)CreateWin32SurfaceKHR},
106783616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetPhysicalDeviceWin32PresentationSupportKHR", (void*)GetPhysicalDeviceWin32PresentationSupportKHR},
106793616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski#endif
106803616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski#ifdef VK_USE_PLATFORM_XCB_KHR
106813616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateXcbSurfaceKHR", (void*)CreateXcbSurfaceKHR},
106823616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetPhysicalDeviceXcbPresentationSupportKHR", (void*)GetPhysicalDeviceXcbPresentationSupportKHR},
106833616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski#endif
106843616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski#ifdef VK_USE_PLATFORM_XLIB_KHR
106853616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateXlibSurfaceKHR", (void*)CreateXlibSurfaceKHR},
106863616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetPhysicalDeviceXlibPresentationSupportKHR", (void*)GetPhysicalDeviceXlibPresentationSupportKHR},
106873616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski#endif
106883616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateDisplayPlaneSurfaceKHR", (void*)CreateDisplayPlaneSurfaceKHR},
106893616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroySurfaceKHR", (void*)DestroySurfaceKHR},
106903616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetPhysicalDeviceSurfaceCapabilitiesKHR", (void*)GetPhysicalDeviceSurfaceCapabilitiesKHR},
106913616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetPhysicalDeviceSurfaceCapabilities2KHR", (void*)GetPhysicalDeviceSurfaceCapabilities2KHR},
106923616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetPhysicalDeviceSurfaceCapabilities2EXT", (void*)GetPhysicalDeviceSurfaceCapabilities2EXT},
106933616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetPhysicalDeviceSurfaceSupportKHR", (void*)GetPhysicalDeviceSurfaceSupportKHR},
106943616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetPhysicalDeviceSurfacePresentModesKHR", (void*)GetPhysicalDeviceSurfacePresentModesKHR},
106953616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetPhysicalDeviceSurfaceFormatsKHR", (void*)GetPhysicalDeviceSurfaceFormatsKHR},
106963616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetPhysicalDeviceSurfaceFormats2KHR", (void*)GetPhysicalDeviceSurfaceFormats2KHR},
106973616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetPhysicalDeviceQueueFamilyProperties2KHR", (void*)GetPhysicalDeviceQueueFamilyProperties2KHR},
106983616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkEnumeratePhysicalDeviceGroupsKHX", (void*)EnumeratePhysicalDeviceGroupsKHX},
106993616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateDebugReportCallbackEXT", (void*)CreateDebugReportCallbackEXT},
107003616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroyDebugReportCallbackEXT", (void*)DestroyDebugReportCallbackEXT},
107013616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDebugReportMessageEXT", (void*)DebugReportMessageEXT},
10702991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    {"vkGetPhysicalDeviceDisplayPlanePropertiesKHR", (void*)GetPhysicalDeviceDisplayPlanePropertiesKHR},
10703991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    {"GetDisplayPlaneSupportedDisplaysKHR", (void*)GetDisplayPlaneSupportedDisplaysKHR},
10704991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    {"GetDisplayPlaneCapabilitiesKHR", (void*)GetDisplayPlaneCapabilitiesKHR},
107053616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski};
10706b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young
107073616276bb0053c612c0a8d223e81ae3808b1b2c4Mark LobodzinskiVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
107083616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    assert(device);
107093616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    layer_data *device_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
107105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
107113616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    // Is API to be intercepted by this layer?
107123616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    const auto &item = name_to_funcptr_map.find(funcName);
107133616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    if (item != name_to_funcptr_map.end()) {
107143616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski        return reinterpret_cast<PFN_vkVoidFunction>(item->second);
107153616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    }
1071609a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu
107173616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    auto &table = device_data->dispatch_table;
10718cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (!table.GetDeviceProcAddr) return nullptr;
107193616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    return table.GetDeviceProcAddr(device, funcName);
107205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
107215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
1072289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
107233616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    instance_layer_data *instance_data;
107243616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    // Is API to be intercepted by this layer?
107253616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    const auto &item = name_to_funcptr_map.find(funcName);
107263616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    if (item != name_to_funcptr_map.end()) {
107273616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski        return reinterpret_cast<PFN_vkVoidFunction>(item->second);
107283616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    }
10729b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young
107303616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map);
107314a0754042cf090e131e9e769d8a3633c228625beChris Forbes    auto &table = instance_data->dispatch_table;
10732cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (!table.GetInstanceProcAddr) return nullptr;
107334a0754042cf090e131e9e769d8a3633c228625beChris Forbes    return table.GetInstanceProcAddr(instance, funcName);
107345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
1073508939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu
10736b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark YoungVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetPhysicalDeviceProcAddr(VkInstance instance, const char *funcName) {
10737b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young    assert(instance);
1073856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map);
10739b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young
10740b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young    auto &table = instance_data->dispatch_table;
10741cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (!table.GetPhysicalDeviceProcAddr) return nullptr;
10742b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young    return table.GetPhysicalDeviceProcAddr(instance, funcName);
10743b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young}
10744b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young
10745cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski}  // namespace core_validation
10746d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu
10747a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu// loader-layer interface v0, just wrappers since there is only a layer
10748d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu
10749bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
10750bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                                                      VkExtensionProperties *pProperties) {
10751a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu    return core_validation::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
1075208939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu}
1075308939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu
10754bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
10755bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                                                  VkLayerProperties *pProperties) {
10756a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu    return core_validation::EnumerateInstanceLayerProperties(pCount, pProperties);
1075708939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu}
1075808939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu
10759bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
10760bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                                                VkLayerProperties *pProperties) {
10761a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu    // the layer command handles VK_NULL_HANDLE just fine internally
10762a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu    assert(physicalDevice == VK_NULL_HANDLE);
10763a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu    return core_validation::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
10764d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu}
10765d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu
10766d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I WuVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
10767d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu                                                                                    const char *pLayerName, uint32_t *pCount,
10768d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu                                                                                    VkExtensionProperties *pProperties) {
10769a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu    // the layer command handles VK_NULL_HANDLE just fine internally
10770a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu    assert(physicalDevice == VK_NULL_HANDLE);
10771a8f4a23b1e9c068717eda47cc583a93f447c77e3Chia-I Wu    return core_validation::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
10772d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu}
10773d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu
10774d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I WuVK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
1077589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu    return core_validation::GetDeviceProcAddr(dev, funcName);
10776d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu}
10777d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu
10778d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I WuVK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
1077989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu    return core_validation::GetInstanceProcAddr(instance, funcName);
1078008939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu}
10781b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young
10782bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance,
10783bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                                                           const char *funcName) {
10784b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young    return core_validation::GetPhysicalDeviceProcAddr(instance, funcName);
10785b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young}
10786b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young
10787b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark YoungVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
10788b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young    assert(pVersionStruct != NULL);
10789b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young    assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
10790b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young
10791b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young    // Fill in the function pointers if our version is at least capable of having the structure contain them.
10792b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young    if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
10793b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young        pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
10794b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young        pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
10795b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young        pVersionStruct->pfnGetPhysicalDeviceProcAddr = vk_layerGetPhysicalDeviceProcAddr;
10796b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young    }
10797b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young
10798b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young    if (pVersionStruct->loaderLayerInterfaceVersion < CURRENT_LOADER_LAYER_INTERFACE_VERSION) {
10799b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young        core_validation::loader_layer_if_version = pVersionStruct->loaderLayerInterfaceVersion;
10800b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young    } else if (pVersionStruct->loaderLayerInterfaceVersion > CURRENT_LOADER_LAYER_INTERFACE_VERSION) {
10801b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young        pVersionStruct->loaderLayerInterfaceVersion = CURRENT_LOADER_LAYER_INTERFACE_VERSION;
10802b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young    }
10803b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young
10804b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young    return VK_SUCCESS;
10805b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young}
10806