core_validation.cpp revision f85ac0ee54f3cfbac8bb9bf046de2f502e9b8bff
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"
70b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf#include "vk_typemap_helper.h"
715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#if defined __ANDROID__
735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#include <android/log.h>
745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#define LOGCONSOLE(...) ((void)__android_log_print(ANDROID_LOG_INFO, "DS", __VA_ARGS__))
755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#else
76cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#define LOGCONSOLE(...)      \
77cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    {                        \
78cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        printf(__VA_ARGS__); \
79cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        printf("\n");        \
80c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine    }
815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#endif
825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
835770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus// TODO: remove on NDK update (r15 will probably have proper STL impl)
845770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus#ifdef __ANDROID__
855770f8ad21c40b2475201e73e9368a899b6886d0Petr Krausnamespace std {
865770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
875770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraustemplate <typename T>
885770f8ad21c40b2475201e73e9368a899b6886d0Petr Krausstd::string to_string(T var) {
895770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    std::ostringstream ss;
905770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    ss << var;
915770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    return ss.str();
925770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus}
935770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus}
945770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus#endif
955770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
96d147a5463f8581604ca542aa1a44a27e512e0f60Mike Stroyan// This intentionally includes a cpp file
97d147a5463f8581604ca542aa1a44a27e512e0f60Mike Stroyan#include "vk_safe_struct.cpp"
98d147a5463f8581604ca542aa1a44a27e512e0f60Mike Stroyan
99ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbesusing mutex_t = std::mutex;
100ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbesusing lock_guard_t = std::lock_guard<mutex_t>;
101ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbesusing unique_lock_t = std::unique_lock<mutex_t>;
102ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes
103d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wunamespace core_validation {
104d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu
1055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisusing std::unordered_map;
1065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisusing std::unordered_set;
1070c55adf45a81f44300db04ec71a797d790ef103cTobin Ehlisusing std::unique_ptr;
1080c55adf45a81f44300db04ec71a797d790ef103cTobin Ehlisusing std::vector;
1090c55adf45a81f44300db04ec71a797d790ef103cTobin Ehlisusing std::string;
1100c55adf45a81f44300db04ec71a797d790ef103cTobin Ehlisusing std::stringstream;
1110c55adf45a81f44300db04ec71a797d790ef103cTobin Ehlisusing std::max;
1125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
1135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// WSI Image Objects bypass usual Image Object creation methods.  A special Memory
1145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Object value will be used to identify them internally.
1155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic const VkDeviceMemory MEMTRACKER_SWAP_CHAIN_IMAGE_KEY = (VkDeviceMemory)(-1);
116888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis// 2nd special memory handle used to flag object as unbound from memory
117888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlisstatic const VkDeviceMemory MEMORY_UNBOUND = VkDeviceMemory(~((uint64_t)(0)) - 1);
118b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis
1192e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill// A special value of (0xFFFFFFFF, 0xFFFFFFFF) indicates that the surface size will be determined
1202e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill// by the extent of a swapchain targeting the surface.
1212e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madillstatic const uint32_t kSurfaceSizeFromSwapchain = 0xFFFFFFFFu;
1222e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill
123f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbesstruct instance_layer_data {
124d3578035fec44db2380099c2f59d3e4d8e0b98d6Chris Forbes    VkInstance instance = VK_NULL_HANDLE;
125d3578035fec44db2380099c2f59d3e4d8e0b98d6Chris Forbes    debug_report_data *report_data = nullptr;
1265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    std::vector<VkDebugReportCallbackEXT> logging_callback;
1279172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes    VkLayerInstanceDispatchTable dispatch_table;
1289172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes
129219f00ffed576643641976122fa1db8e5fce5dc1Chris Forbes    CALL_STATE vkEnumeratePhysicalDevicesState = UNCALLED;
130219f00ffed576643641976122fa1db8e5fce5dc1Chris Forbes    uint32_t physical_devices_count = 0;
131b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young    CALL_STATE vkEnumeratePhysicalDeviceGroupsState = UNCALLED;
132b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young    uint32_t physical_device_groups_count = 0;
133219f00ffed576643641976122fa1db8e5fce5dc1Chris Forbes    CHECK_DISABLED disabled = {};
134219f00ffed576643641976122fa1db8e5fce5dc1Chris Forbes
135f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbes    unordered_map<VkPhysicalDevice, PHYSICAL_DEVICE_STATE> physical_device_map;
136747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    unordered_map<VkSurfaceKHR, SURFACE_STATE> surface_map;
137747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
1380cf009a4e2a5c22e4645f343c7a998f188a22015Chris Forbes    InstanceExtensions extensions;
139f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbes};
140f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbes
141f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbesstruct layer_data {
142f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbes    debug_report_data *report_data = nullptr;
1434a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkLayerDispatchTable dispatch_table;
14494c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis
145a149f1a0cb39b48b19822c8cf9ef2426cd2251dfMark Lobodzinski    DeviceExtensions extensions = {};
146cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    unordered_set<VkQueue> queues;  // All queues under given device
1475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Layer specific data
148d31a44af6da568692a73201825459689c9431867Tobin Ehlis    unordered_map<VkSampler, unique_ptr<SAMPLER_STATE>> samplerMap;
14979fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis    unordered_map<VkImageView, unique_ptr<IMAGE_VIEW_STATE>> imageViewMap;
1501facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis    unordered_map<VkImage, unique_ptr<IMAGE_STATE>> imageMap;
15139267c0c27b8f032f05a6747eb02d4508247fdc1Tobin Ehlis    unordered_map<VkBufferView, unique_ptr<BUFFER_VIEW_STATE>> bufferViewMap;
1525cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis    unordered_map<VkBuffer, unique_ptr<BUFFER_STATE>> bufferMap;
15363cddeb5593a0ead9ecd5f74d05f506b37d7ac66Chris Forbes    unordered_map<VkPipeline, unique_ptr<PIPELINE_STATE>> pipelineMap;
1548d6a38de0389036581ada119e548180c614fe0efChris Forbes    unordered_map<VkCommandPool, COMMAND_POOL_NODE> commandPoolMap;
155a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis    unordered_map<VkDescriptorPool, DESCRIPTOR_POOL_STATE *> descriptorPoolMap;
156397d27da37095073c8b86f9ff5289d0a39ce486eTobin Ehlis    unordered_map<VkDescriptorSet, cvdescriptorset::DescriptorSet *> setMap;
1573f75ec6fa8700769a790d84e07c270579ded5468Tobin Ehlis    unordered_map<VkDescriptorSetLayout, std::shared_ptr<cvdescriptorset::DescriptorSetLayout const>> descriptorSetLayoutMap;
1585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    unordered_map<VkPipelineLayout, PIPELINE_LAYOUT_NODE> pipelineLayoutMap;
15957fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis    unordered_map<VkDeviceMemory, unique_ptr<DEVICE_MEM_INFO>> memObjMap;
1605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    unordered_map<VkFence, FENCE_NODE> fenceMap;
16136c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlis    unordered_map<VkQueue, QUEUE_STATE> queueMap;
1624710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis    unordered_map<VkEvent, EVENT_STATE> eventMap;
1635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    unordered_map<QueryObject, bool> queryToStateMap;
1645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    unordered_map<VkQueryPool, QUERY_POOL_NODE> queryPoolMap;
1655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    unordered_map<VkSemaphore, SEMAPHORE_NODE> semaphoreMap;
16672d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis    unordered_map<VkCommandBuffer, GLOBAL_CB_NODE *> commandBufferMap;
167c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis    unordered_map<VkFramebuffer, unique_ptr<FRAMEBUFFER_STATE>> frameBufferMap;
1685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    unordered_map<VkImage, vector<ImageSubresourcePair>> imageSubresourceMap;
1695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    unordered_map<ImageSubresourcePair, IMAGE_LAYOUT_NODE> imageLayoutMap;
170ba9be0cec36d930fc0d5a0cbfbc00b0df49b08e4Tobin Ehlis    unordered_map<VkRenderPass, std::shared_ptr<RENDER_PASS_STATE>> renderPassMap;
171918c283ac4f8c604b79abd0c8b5706d2a7352a34Chris Forbes    unordered_map<VkShaderModule, unique_ptr<shader_module>> shaderModuleMap;
1726246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski    unordered_map<VkDescriptorUpdateTemplateKHR, unique_ptr<TEMPLATE_STATE>> desc_template_map;
17316a1f8f9c4af479b1873e82ff02360817fb658acChris Forbes    unordered_map<VkSwapchainKHR, std::unique_ptr<SWAPCHAIN_NODE>> swapchainMap;
17407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski
175d3578035fec44db2380099c2f59d3e4d8e0b98d6Chris Forbes    VkDevice device = VK_NULL_HANDLE;
176ec85232c4d8d9ddf7d2ae57cb8203c5ab52c1106Mark Lobodzinski    VkPhysicalDevice physical_device = VK_NULL_HANDLE;
1775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
178cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    instance_layer_data *instance_data = nullptr;  // from device to enclosing instance
17907a464bd7fec9583f346b8c4b8d43c88d2e9ffa4Chris Forbes
180f71dd305f197826a61f398bff725267a20ea1d90Chris Forbes    VkPhysicalDeviceFeatures enabled_features = {};
1815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Device specific data
182d3578035fec44db2380099c2f59d3e4d8e0b98d6Chris Forbes    PHYS_DEV_PROPERTIES_NODE phys_dev_properties = {};
183d3578035fec44db2380099c2f59d3e4d8e0b98d6Chris Forbes    VkPhysicalDeviceMemoryProperties phys_dev_mem_props = {};
184e47dbc3f3340fa177d877a67b2adb76a570027e5Mark Lobodzinski    VkPhysicalDeviceProperties phys_dev_props = {};
18585926a33d427ee62f395a50886db980127063c72Mike Schuchardt    bool external_sync_warning = false;
1865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis};
1875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
188b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis// TODO : Do we need to guard access to layer_data_map w/ lock?
189b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlisstatic unordered_map<void *, layer_data *> layer_data_map;
190f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbesstatic unordered_map<void *, instance_layer_data *> instance_layer_data_map;
191b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis
192b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Youngstatic uint32_t loader_layer_if_version = CURRENT_LOADER_LAYER_INTERFACE_VERSION;
193b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young
194e11120777bcd1543455d1de54b89292879bcd2bbChia-I Wustatic const VkLayerProperties global_layer = {
195f1ea418f193d10a8455cdf47e0eeeeb1f4d8b5bfJon Ashburn    "VK_LAYER_LUNARG_core_validation", VK_LAYER_API_VERSION, 1, "LunarG Validation Layer",
196e11120777bcd1543455d1de54b89292879bcd2bbChia-I Wu};
1975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
198fe772548f7a48b12772483e8faecc956fb76eb42Chris Forbesstatic const VkExtensionProperties device_extensions[] = {
199fe772548f7a48b12772483e8faecc956fb76eb42Chris Forbes  { VK_EXT_VALIDATION_CACHE_EXTENSION_NAME, VK_EXT_VALIDATION_CACHE_SPEC_VERSION },
200fe772548f7a48b12772483e8faecc956fb76eb42Chris Forbes};
201fe772548f7a48b12772483e8faecc956fb76eb42Chris Forbes
202cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskitemplate <class TCreateInfo>
203cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskivoid ValidateLayerOrdering(const TCreateInfo &createInfo) {
2045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    bool foundLayer = false;
2055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < createInfo.enabledLayerCount; ++i) {
206e11120777bcd1543455d1de54b89292879bcd2bbChia-I Wu        if (!strcmp(createInfo.ppEnabledLayerNames[i], global_layer.layerName)) {
2075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            foundLayer = true;
2085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
2095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // This has to be logged to console as we don't have a callback at this point.
2105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (!foundLayer && !strcmp(createInfo.ppEnabledLayerNames[0], "VK_LAYER_GOOGLE_unique_objects")) {
211bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski            LOGCONSOLE("Cannot activate layer VK_LAYER_GOOGLE_unique_objects prior to activating %s.", global_layer.layerName);
2125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
2135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
2145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
2155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// TODO : This can be much smarter, using separate locks for separate global data
217ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbesstatic mutex_t global_lock;
218593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis
21979fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis// Return IMAGE_VIEW_STATE ptr for specified imageView or else NULL
2209a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisIMAGE_VIEW_STATE *GetImageViewState(const layer_data *dev_data, VkImageView image_view) {
2212c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis    auto iv_it = dev_data->imageViewMap.find(image_view);
2222c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis    if (iv_it == dev_data->imageViewMap.end()) {
2232c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis        return nullptr;
2242c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis    }
2252c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis    return iv_it->second.get();
2262c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis}
2279a55ca3674bb3fac3fbdfca9515a16a224aa9055Tobin Ehlis// Return sampler node ptr for specified sampler or else NULL
2289a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisSAMPLER_STATE *GetSamplerState(const layer_data *dev_data, VkSampler sampler) {
2292c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis    auto sampler_it = dev_data->samplerMap.find(sampler);
2302c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis    if (sampler_it == dev_data->samplerMap.end()) {
2319a55ca3674bb3fac3fbdfca9515a16a224aa9055Tobin Ehlis        return nullptr;
2329a55ca3674bb3fac3fbdfca9515a16a224aa9055Tobin Ehlis    }
2339a55ca3674bb3fac3fbdfca9515a16a224aa9055Tobin Ehlis    return sampler_it->second.get();
2349a55ca3674bb3fac3fbdfca9515a16a224aa9055Tobin Ehlis}
2355cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis// Return image state ptr for specified image or else NULL
2369a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisIMAGE_STATE *GetImageState(const layer_data *dev_data, VkImage image) {
2376d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis    auto img_it = dev_data->imageMap.find(image);
2386d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis    if (img_it == dev_data->imageMap.end()) {
2396d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis        return nullptr;
2406d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis    }
2416d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis    return img_it->second.get();
2426d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis}
2435cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis// Return buffer state ptr for specified buffer or else NULL
2449a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisBUFFER_STATE *GetBufferState(const layer_data *dev_data, VkBuffer buffer) {
2452c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis    auto buff_it = dev_data->bufferMap.find(buffer);
2462c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis    if (buff_it == dev_data->bufferMap.end()) {
2478718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis        return nullptr;
2488718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis    }
2498718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis    return buff_it->second.get();
2508718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis}
251b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis// Return swapchain node for specified swapchain or else NULL
2529a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisSWAPCHAIN_NODE *GetSwapchainNode(const layer_data *dev_data, VkSwapchainKHR swapchain) {
25316a1f8f9c4af479b1873e82ff02360817fb658acChris Forbes    auto swp_it = dev_data->swapchainMap.find(swapchain);
25416a1f8f9c4af479b1873e82ff02360817fb658acChris Forbes    if (swp_it == dev_data->swapchainMap.end()) {
255b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis        return nullptr;
256b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis    }
2573f687bf405355f3eec6bd1bc0e8d04daba37a0f9Tobin Ehlis    return swp_it->second.get();
258b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis}
2592f2db584f5d79892bd84d0a24b8ca3499985a5c2Tobin Ehlis// Return buffer node ptr for specified buffer or else NULL
2609a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisBUFFER_VIEW_STATE *GetBufferViewState(const layer_data *dev_data, VkBufferView buffer_view) {
26151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    auto bv_it = dev_data->bufferViewMap.find(buffer_view);
26251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    if (bv_it == dev_data->bufferViewMap.end()) {
2632f2db584f5d79892bd84d0a24b8ca3499985a5c2Tobin Ehlis        return nullptr;
2642f2db584f5d79892bd84d0a24b8ca3499985a5c2Tobin Ehlis    }
2652f2db584f5d79892bd84d0a24b8ca3499985a5c2Tobin Ehlis    return bv_it->second.get();
2662f2db584f5d79892bd84d0a24b8ca3499985a5c2Tobin Ehlis}
2678718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis
2689a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisFENCE_NODE *GetFenceNode(layer_data *dev_data, VkFence fence) {
26966fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes    auto it = dev_data->fenceMap.find(fence);
27066fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes    if (it == dev_data->fenceMap.end()) {
27166fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes        return nullptr;
27266fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes    }
27366fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes    return &it->second;
27466fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes}
27566fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes
2769a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisEVENT_STATE *GetEventNode(layer_data *dev_data, VkEvent event) {
2779556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis    auto it = dev_data->eventMap.find(event);
2789556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis    if (it == dev_data->eventMap.end()) {
2799556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis        return nullptr;
2809556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis    }
2819556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis    return &it->second;
2829556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis}
2839556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis
2849a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisQUERY_POOL_NODE *GetQueryPoolNode(layer_data *dev_data, VkQueryPool query_pool) {
285ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis    auto it = dev_data->queryPoolMap.find(query_pool);
286ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis    if (it == dev_data->queryPoolMap.end()) {
287ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis        return nullptr;
288ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis    }
289ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis    return &it->second;
290ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis}
291ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis
2929a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisQUEUE_STATE *GetQueueState(layer_data *dev_data, VkQueue queue) {
29366fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes    auto it = dev_data->queueMap.find(queue);
29466fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes    if (it == dev_data->queueMap.end()) {
29566fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes        return nullptr;
29666fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes    }
29766fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes    return &it->second;
29866fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes}
29966fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes
3009a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisSEMAPHORE_NODE *GetSemaphoreNode(layer_data *dev_data, VkSemaphore semaphore) {
3015e92f3cfdca6a52a3dcefd053c41f728bd036cebChris Forbes    auto it = dev_data->semaphoreMap.find(semaphore);
3025e92f3cfdca6a52a3dcefd053c41f728bd036cebChris Forbes    if (it == dev_data->semaphoreMap.end()) {
3035e92f3cfdca6a52a3dcefd053c41f728bd036cebChris Forbes        return nullptr;
3045e92f3cfdca6a52a3dcefd053c41f728bd036cebChris Forbes    }
3055e92f3cfdca6a52a3dcefd053c41f728bd036cebChris Forbes    return &it->second;
3065e92f3cfdca6a52a3dcefd053c41f728bd036cebChris Forbes}
3075e92f3cfdca6a52a3dcefd053c41f728bd036cebChris Forbes
3089a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisCOMMAND_POOL_NODE *GetCommandPoolNode(layer_data *dev_data, VkCommandPool pool) {
3098d6a38de0389036581ada119e548180c614fe0efChris Forbes    auto it = dev_data->commandPoolMap.find(pool);
3108d6a38de0389036581ada119e548180c614fe0efChris Forbes    if (it == dev_data->commandPoolMap.end()) {
3118d6a38de0389036581ada119e548180c614fe0efChris Forbes        return nullptr;
3128d6a38de0389036581ada119e548180c614fe0efChris Forbes    }
3138d6a38de0389036581ada119e548180c614fe0efChris Forbes    return &it->second;
3148d6a38de0389036581ada119e548180c614fe0efChris Forbes}
3153bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes
3169a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisPHYSICAL_DEVICE_STATE *GetPhysicalDeviceState(instance_layer_data *instance_data, VkPhysicalDevice phys) {
317f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbes    auto it = instance_data->physical_device_map.find(phys);
318f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbes    if (it == instance_data->physical_device_map.end()) {
3193bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes        return nullptr;
3203bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes    }
3213bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes    return &it->second;
3223bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes}
3233bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes
3249a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisSURFACE_STATE *GetSurfaceState(instance_layer_data *instance_data, VkSurfaceKHR surface) {
325747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    auto it = instance_data->surface_map.find(surface);
326747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    if (it == instance_data->surface_map.end()) {
327747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes        return nullptr;
328747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    }
329747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    return &it->second;
330747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes}
331747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
332d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris ForbesDeviceExtensions const *GetEnabledExtensions(layer_data const *dev_data) {
333d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes    return &dev_data->extensions;
334d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes}
335d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes
336f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis// Return ptr to memory binding for given handle of specified type
3377a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinskistatic BINDABLE *GetObjectMemBinding(layer_data *dev_data, uint64_t handle, VulkanObjectType type) {
3385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    switch (type) {
3397a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski        case kVulkanObjectTypeImage:
3409a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            return GetImageState(dev_data, VkImage(handle));
3417a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski        case kVulkanObjectTypeBuffer:
3429a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            return GetBufferState(dev_data, VkBuffer(handle));
343cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        default:
344cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            break;
3455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
34694c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis    return nullptr;
3475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
34872d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis// prototype
3499a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisGLOBAL_CB_NODE *GetCBNode(layer_data const *, const VkCommandBuffer);
35072d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis
3515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Return ptr to info in map container containing mem, or NULL if not found
3525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis//  Calls to this function should be wrapped in mutex
3539a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisDEVICE_MEM_INFO *GetMemObjInfo(const layer_data *dev_data, const VkDeviceMemory mem) {
35457fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis    auto mem_it = dev_data->memObjMap.find(mem);
35557fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis    if (mem_it == dev_data->memObjMap.end()) {
3565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return NULL;
3575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
35857fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis    return mem_it->second.get();
3595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
3605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
36151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic void add_mem_obj_info(layer_data *dev_data, void *object, const VkDeviceMemory mem,
3625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                             const VkMemoryAllocateInfo *pAllocateInfo) {
3635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    assert(object != NULL);
3645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
36551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    dev_data->memObjMap[mem] = unique_ptr<DEVICE_MEM_INFO>(new DEVICE_MEM_INFO(object, mem, pAllocateInfo));
366ee0b33024b1641ad3bb153259cf71d42675e4652Mike Schuchardt
367ee0b33024b1641ad3bb153259cf71d42675e4652Mike Schuchardt    if (pAllocateInfo->pNext) {
368ee0b33024b1641ad3bb153259cf71d42675e4652Mike Schuchardt        auto struct_header = reinterpret_cast<const GENERIC_HEADER *>(pAllocateInfo->pNext);
369ee0b33024b1641ad3bb153259cf71d42675e4652Mike Schuchardt        while (struct_header) {
370ee0b33024b1641ad3bb153259cf71d42675e4652Mike Schuchardt            if (VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR == struct_header->sType ||
371ee0b33024b1641ad3bb153259cf71d42675e4652Mike Schuchardt                VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR == struct_header->sType) {
372ee0b33024b1641ad3bb153259cf71d42675e4652Mike Schuchardt                dev_data->memObjMap[mem]->global_valid = true;
373ee0b33024b1641ad3bb153259cf71d42675e4652Mike Schuchardt                break;
374ee0b33024b1641ad3bb153259cf71d42675e4652Mike Schuchardt            }
375ee0b33024b1641ad3bb153259cf71d42675e4652Mike Schuchardt            struct_header = reinterpret_cast<const GENERIC_HEADER *>(struct_header->pNext);
376ee0b33024b1641ad3bb153259cf71d42675e4652Mike Schuchardt        }
377ee0b33024b1641ad3bb153259cf71d42675e4652Mike Schuchardt    }
3785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
379dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis
380cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis// For given bound_object_handle, bound to given mem allocation, verify that the range for the bound object is valid
3817a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinskistatic bool ValidateMemoryIsValid(layer_data *dev_data, VkDeviceMemory mem, uint64_t bound_object_handle, VulkanObjectType type,
3827a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski                                  const char *functionName) {
3839a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    DEVICE_MEM_INFO *mem_info = GetMemObjInfo(dev_data, mem);
384f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis    if (mem_info) {
385f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis        if (!mem_info->bound_ranges[bound_object_handle].valid) {
386f48a83f5b5548cd46a12770c7542ff902537ad3eKarl Schultz            return log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
3879b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                           HandleToUint64(mem), __LINE__, MEMTRACK_INVALID_MEM_REGION, "MEM",
388dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis                           "%s: Cannot read invalid region of memory allocation 0x%" PRIx64 " for bound %s object 0x%" PRIx64
389dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis                           ", please fill the memory before using.",
3909b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                           functionName, HandleToUint64(mem), object_string[type], bound_object_handle);
391f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis        }
392f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis    }
393f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis    return false;
394f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis}
3951facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis// For given image_state
3961facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis//  If mem is special swapchain key, then verify that image_state valid member is true
397f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis//  Else verify that the image's bound memory range is valid
39860568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinskibool ValidateImageMemoryIsValid(layer_data *dev_data, IMAGE_STATE *image_state, const char *functionName) {
399e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis    if (image_state->binding.mem == MEMTRACKER_SWAP_CHAIN_IMAGE_KEY) {
4001facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis        if (!image_state->valid) {
401f48a83f5b5548cd46a12770c7542ff902537ad3eKarl Schultz            return log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
4029b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                           HandleToUint64(image_state->binding.mem), __LINE__, MEMTRACK_INVALID_MEM_REGION, "MEM",
403414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                           "%s: Cannot read invalid swapchain image 0x%" PRIx64 ", please fill the memory before using.",
4049b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                           functionName, HandleToUint64(image_state->image));
4055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
4065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    } else {
4079b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus        return ValidateMemoryIsValid(dev_data, image_state->binding.mem, HandleToUint64(image_state->image), kVulkanObjectTypeImage,
4089b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                     functionName);
4095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
4105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return false;
4115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
4125cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis// For given buffer_state, verify that the range it's bound to is valid
413c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinskibool ValidateBufferMemoryIsValid(layer_data *dev_data, BUFFER_STATE *buffer_state, const char *functionName) {
4149b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus    return ValidateMemoryIsValid(dev_data, buffer_state->binding.mem, HandleToUint64(buffer_state->buffer), kVulkanObjectTypeBuffer,
4159b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                 functionName);
416f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis}
417f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis// For the given memory allocation, set the range bound by the given handle object to the valid param value
418f989de4217bce0f293121d0da53dc8328276370fTobin Ehlisstatic void SetMemoryValid(layer_data *dev_data, VkDeviceMemory mem, uint64_t handle, bool valid) {
4199a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    DEVICE_MEM_INFO *mem_info = GetMemObjInfo(dev_data, mem);
420f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis    if (mem_info) {
421f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis        mem_info->bound_ranges[handle].valid = valid;
422f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis    }
423f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis}
424f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis// For given image node
4251facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis//  If mem is special swapchain key, then set entire image_state to valid param value
426f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis//  Else set the image's bound memory range to valid param value
427623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinskivoid SetImageMemoryValid(layer_data *dev_data, IMAGE_STATE *image_state, bool valid) {
428e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis    if (image_state->binding.mem == MEMTRACKER_SWAP_CHAIN_IMAGE_KEY) {
4291facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis        image_state->valid = valid;
4305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    } else {
4319b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus        SetMemoryValid(dev_data, image_state->binding.mem, HandleToUint64(image_state->image), valid);
4325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
4335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
434f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis// For given buffer node set the buffer's bound memory range to valid param value
435c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinskivoid SetBufferMemoryValid(layer_data *dev_data, BUFFER_STATE *buffer_state, bool valid) {
4369b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus    SetMemoryValid(dev_data, buffer_state->binding.mem, HandleToUint64(buffer_state->buffer), valid);
437f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis}
438ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis
43956f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis// Create binding link between given sampler and command buffer node
440d31a44af6da568692a73201825459689c9431867Tobin Ehlisvoid AddCommandBufferBindingSampler(GLOBAL_CB_NODE *cb_node, SAMPLER_STATE *sampler_state) {
441d31a44af6da568692a73201825459689c9431867Tobin Ehlis    sampler_state->cb_bindings.insert(cb_node);
4429b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus    cb_node->object_bindings.insert({HandleToUint64(sampler_state->sampler), kVulkanObjectTypeSampler});
44356f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis}
44456f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis
44556f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis// Create binding link between given image node and command buffer node
4461facd2c91911508b9fb61f54a56269841299f663Tobin Ehlisvoid AddCommandBufferBindingImage(const layer_data *dev_data, GLOBAL_CB_NODE *cb_node, IMAGE_STATE *image_state) {
447ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    // Skip validation if this image was created through WSI
448e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis    if (image_state->binding.mem != MEMTRACKER_SWAP_CHAIN_IMAGE_KEY) {
449ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        // First update CB binding in MemObj mini CB list
450d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis        for (auto mem_binding : image_state->GetBoundMemory()) {
4519a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            DEVICE_MEM_INFO *pMemInfo = GetMemObjInfo(dev_data, mem_binding);
452d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis            if (pMemInfo) {
453d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis                pMemInfo->cb_bindings.insert(cb_node);
454d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis                // Now update CBInfo's Mem reference list
455d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis                cb_node->memObjs.insert(mem_binding);
456d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis            }
457ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        }
458f940225c9e5e3e14b3f5a32d3ea360b585614600Tobin Ehlis        // Now update cb binding for image
4599b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus        cb_node->object_bindings.insert({HandleToUint64(image_state->image), kVulkanObjectTypeImage});
4601facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis        image_state->cb_bindings.insert(cb_node);
461ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    }
462ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis}
463ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis
46403ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis// Create binding link between given image view node and its image with command buffer node
46503ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlisvoid AddCommandBufferBindingImageView(const layer_data *dev_data, GLOBAL_CB_NODE *cb_node, IMAGE_VIEW_STATE *view_state) {
46603ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis    // First add bindings for imageView
46703ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis    view_state->cb_bindings.insert(cb_node);
4689b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus    cb_node->object_bindings.insert({HandleToUint64(view_state->image_view), kVulkanObjectTypeImageView});
4699a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto image_state = GetImageState(dev_data, view_state->create_info.image);
47003ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis    // Add bindings for image within imageView
4711facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis    if (image_state) {
4721facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis        AddCommandBufferBindingImage(dev_data, cb_node, image_state);
47303ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis    }
47403ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis}
47503ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis
476ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis// Create binding link between given buffer node and command buffer node
4775cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlisvoid AddCommandBufferBindingBuffer(const layer_data *dev_data, GLOBAL_CB_NODE *cb_node, BUFFER_STATE *buffer_state) {
478ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    // First update CB binding in MemObj mini CB list
4795cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis    for (auto mem_binding : buffer_state->GetBoundMemory()) {
4809a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        DEVICE_MEM_INFO *pMemInfo = GetMemObjInfo(dev_data, mem_binding);
481d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis        if (pMemInfo) {
482d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis            pMemInfo->cb_bindings.insert(cb_node);
483d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis            // Now update CBInfo's Mem reference list
484d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis            cb_node->memObjs.insert(mem_binding);
485d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis        }
486ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    }
487ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    // Now update cb binding for buffer
4889b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus    cb_node->object_bindings.insert({HandleToUint64(buffer_state->buffer), kVulkanObjectTypeBuffer});
4895cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis    buffer_state->cb_bindings.insert(cb_node);
490ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis}
491ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis
49277b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis// Create binding link between given buffer view node and its buffer with command buffer node
49377b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlisvoid AddCommandBufferBindingBufferView(const layer_data *dev_data, GLOBAL_CB_NODE *cb_node, BUFFER_VIEW_STATE *view_state) {
49477b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis    // First add bindings for bufferView
49577b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis    view_state->cb_bindings.insert(cb_node);
4969b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus    cb_node->object_bindings.insert({HandleToUint64(view_state->buffer_view), kVulkanObjectTypeBufferView});
4979a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto buffer_state = GetBufferState(dev_data, view_state->create_info.buffer);
49877b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis    // Add bindings for buffer within bufferView
4995cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis    if (buffer_state) {
5005cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis        AddCommandBufferBindingBuffer(dev_data, cb_node, buffer_state);
50177b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis    }
50277b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis}
50377b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis
504400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis// For every mem obj bound to particular CB, free bindings related to that CB
505d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlisstatic void clear_cmd_buf_and_mem_references(layer_data *dev_data, GLOBAL_CB_NODE *cb_node) {
506d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis    if (cb_node) {
507d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis        if (cb_node->memObjs.size() > 0) {
508d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis            for (auto mem : cb_node->memObjs) {
5099a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                DEVICE_MEM_INFO *pInfo = GetMemObjInfo(dev_data, mem);
5105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                if (pInfo) {
511d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis                    pInfo->cb_bindings.erase(cb_node);
5125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
5135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
514d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis            cb_node->memObjs.clear();
5155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
5165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
5175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
5185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
519f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis// Clear a single object binding from given memory object, or report error if binding is missing
5207a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinskistatic bool ClearMemoryObjectBinding(layer_data *dev_data, uint64_t handle, VulkanObjectType type, VkDeviceMemory mem) {
5219a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    DEVICE_MEM_INFO *mem_info = GetMemObjInfo(dev_data, mem);
522f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis    // This obj is bound to a memory object. Remove the reference to this object in that memory object's list
523d4cd34fd49caa759cf01cafa5fa271401b17c3b9Jeremy Hayes    if (mem_info) {
524d4cd34fd49caa759cf01cafa5fa271401b17c3b9Jeremy Hayes        mem_info->obj_bindings.erase({handle, type});
525f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis    }
526f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis    return false;
527f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis}
528f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis
529f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis// ClearMemoryObjectBindings clears the binding of objects to memory
530f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis//  For the given object it pulls the memory bindings and makes sure that the bindings
531f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis//  no longer refer to the object being cleared. This occurs when objects are destroyed.
5327a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinskibool ClearMemoryObjectBindings(layer_data *dev_data, uint64_t handle, VulkanObjectType type) {
533f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis    bool skip = false;
534f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis    BINDABLE *mem_binding = GetObjectMemBinding(dev_data, handle, type);
535f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis    if (mem_binding) {
536f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis        if (!mem_binding->sparse) {
537f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis            skip = ClearMemoryObjectBinding(dev_data, handle, type, mem_binding->binding.mem);
538cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        } else {  // Sparse, clear all bindings
539bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski            for (auto &sparse_mem_binding : mem_binding->sparse_bindings) {
540f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis                skip |= ClearMemoryObjectBinding(dev_data, handle, type, sparse_mem_binding.mem);
5415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
5425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
5435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
544f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis    return skip;
5455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
5465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
547888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis// For given mem object, verify that it is not null or UNBOUND, if it is, report error. Return skip value.
548888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlisbool VerifyBoundMemoryIsValid(const layer_data *dev_data, VkDeviceMemory mem, uint64_t handle, const char *api_name,
54935ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis                              const char *type_name, UNIQUE_VALIDATION_ERROR_CODE error_code) {
550888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis    bool result = false;
551888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis    if (VK_NULL_HANDLE == mem) {
552888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis        result = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, handle,
553cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                         __LINE__, error_code, "MEM", "%s: Vk%s object 0x%" PRIxLEAST64
554cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                                                      " used with no memory bound. Memory should be bound by calling "
555cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                                                      "vkBind%sMemory(). %s",
55635ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis                         api_name, type_name, handle, type_name, validation_error_map[error_code]);
557888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis    } else if (MEMORY_UNBOUND == mem) {
558888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis        result = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, handle,
559cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                         __LINE__, error_code, "MEM", "%s: Vk%s object 0x%" PRIxLEAST64
560cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                                                      " used with no memory bound and previously bound memory was freed. "
561cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                                                      "Memory must not be freed prior to this operation. %s",
56235ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis                         api_name, type_name, handle, validation_error_map[error_code]);
563888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis    }
564888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis    return result;
565888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis}
566888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis
567b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski// Check to see if memory was ever bound to this image
56835ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlisbool ValidateMemoryIsBoundToImage(const layer_data *dev_data, const IMAGE_STATE *image_state, const char *api_name,
56935ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis                                  UNIQUE_VALIDATION_ERROR_CODE error_code) {
570b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski    bool result = false;
5711facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis    if (0 == (static_cast<uint32_t>(image_state->createInfo.flags) & VK_IMAGE_CREATE_SPARSE_BINDING_BIT)) {
5729b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus        result = VerifyBoundMemoryIsValid(dev_data, image_state->binding.mem, HandleToUint64(image_state->image), api_name, "Image",
5739b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                          error_code);
574b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski    }
575b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski    return result;
576b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski}
577b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski
578b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski// Check to see if memory was bound to this buffer
57935ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlisbool ValidateMemoryIsBoundToBuffer(const layer_data *dev_data, const BUFFER_STATE *buffer_state, const char *api_name,
58035ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis                                   UNIQUE_VALIDATION_ERROR_CODE error_code) {
581b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski    bool result = false;
5825cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis    if (0 == (static_cast<uint32_t>(buffer_state->createInfo.flags) & VK_BUFFER_CREATE_SPARSE_BINDING_BIT)) {
5839b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus        result = VerifyBoundMemoryIsValid(dev_data, buffer_state->binding.mem, HandleToUint64(buffer_state->buffer), api_name,
5849b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                          "Buffer", error_code);
585b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski    }
586b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski    return result;
587b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski}
588b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski
5893a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// SetMemBinding is used to establish immutable, non-sparse binding between a single image/buffer object and memory object.
5903a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// Corresponding valid usage checks are in ValidateSetMemBinding().
5917a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinskistatic void SetMemBinding(layer_data *dev_data, VkDeviceMemory mem, uint64_t handle, VulkanObjectType type, const char *apiName) {
592c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton    if (mem != VK_NULL_HANDLE) {
593c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton        BINDABLE *mem_binding = GetObjectMemBinding(dev_data, handle, type);
594c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton        assert(mem_binding);
595c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton        DEVICE_MEM_INFO *mem_info = GetMemObjInfo(dev_data, mem);
596c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton        if (mem_info) {
597c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton            mem_info->obj_bindings.insert({handle, type});
598c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton            // For image objects, make sure default memory state is correctly set
599c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton            // TODO : What's the best/correct way to handle this?
6007a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski            if (kVulkanObjectTypeImage == type) {
601c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton                auto const image_state = GetImageState(dev_data, VkImage(handle));
602c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton                if (image_state) {
603c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton                    VkImageCreateInfo ici = image_state->createInfo;
604c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton                    if (ici.usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) {
605c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton                        // TODO::  More memory state transition stuff.
606c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton                    }
607c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton                }
608c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton            }
609c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton            mem_binding->binding.mem = mem;
610c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton        }
611c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton    }
612c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton}
6133a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton
6143a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// Valid usage checks for a call to SetMemBinding().
6153a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// For NULL mem case, output warning
6163a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// Make sure given object is in global object map
6173a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton//  IF a previous binding existed, output validation error
6183a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton//  Otherwise, add reference from objectInfo to memoryInfo
6193a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton//  Add reference off of objInfo
6203a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// TODO: We may need to refactor or pass in multiple valid usage statements to handle multiple valid usage conditions.
6217a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinskistatic bool ValidateSetMemBinding(layer_data *dev_data, VkDeviceMemory mem, uint64_t handle, VulkanObjectType type,
622c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton                                  const char *apiName) {
6233251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
624f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis    // It's an error to bind an object to NULL memory
625d3876b4ff7c293a14f73fe3622513d1fa91bf2d0Jeremy Hayes    if (mem != VK_NULL_HANDLE) {
626f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis        BINDABLE *mem_binding = GetObjectMemBinding(dev_data, handle, type);
627888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis        assert(mem_binding);
62810ffe2d353eaff714ed92a2835af77d8b5042d31Cort        if (mem_binding->sparse) {
629315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis            UNIQUE_VALIDATION_ERROR_CODE error_code = VALIDATION_ERROR_1740082a;
63010ffe2d353eaff714ed92a2835af77d8b5042d31Cort            const char *handle_type = "IMAGE";
63174300755ed9ec780d6073af71e47f201217008d6Cort Stratton            if (strcmp(apiName, "vkBindBufferMemory()") == 0) {
632315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                error_code = VALIDATION_ERROR_1700080c;
63310ffe2d353eaff714ed92a2835af77d8b5042d31Cort                handle_type = "BUFFER";
63410ffe2d353eaff714ed92a2835af77d8b5042d31Cort            } else {
63574300755ed9ec780d6073af71e47f201217008d6Cort Stratton                assert(strcmp(apiName, "vkBindImageMemory()") == 0);
63610ffe2d353eaff714ed92a2835af77d8b5042d31Cort            }
6373251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
6389b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(mem), __LINE__, error_code, "MEM",
6393251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "In %s, attempting to bind memory (0x%" PRIxLEAST64 ") to object (0x%" PRIxLEAST64
6403251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            ") which was created with sparse memory flags (VK_%s_CREATE_SPARSE_*_BIT). %s",
6419b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            apiName, HandleToUint64(mem), handle, handle_type, validation_error_map[error_code]);
64210ffe2d353eaff714ed92a2835af77d8b5042d31Cort        }
6439a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        DEVICE_MEM_INFO *mem_info = GetMemObjInfo(dev_data, mem);
644888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis        if (mem_info) {
6459a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            DEVICE_MEM_INFO *prev_binding = GetMemObjInfo(dev_data, mem_binding->binding.mem);
646888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis            if (prev_binding) {
647315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                UNIQUE_VALIDATION_ERROR_CODE error_code = VALIDATION_ERROR_17400828;
64874300755ed9ec780d6073af71e47f201217008d6Cort Stratton                if (strcmp(apiName, "vkBindBufferMemory()") == 0) {
649315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                    error_code = VALIDATION_ERROR_1700080a;
65098c2a17e1a549df84f4239f619bc0955f632cb43Cort                } else {
65174300755ed9ec780d6073af71e47f201217008d6Cort Stratton                    assert(strcmp(apiName, "vkBindImageMemory()") == 0);
65298c2a17e1a549df84f4239f619bc0955f632cb43Cort                }
6533251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
6549b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                HandleToUint64(mem), __LINE__, error_code, "MEM",
6553251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "In %s, attempting to bind memory (0x%" PRIxLEAST64 ") to object (0x%" PRIxLEAST64
6563251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                ") which has already been bound to mem object 0x%" PRIxLEAST64 ". %s",
6579b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                apiName, HandleToUint64(mem), handle, HandleToUint64(prev_binding->mem),
6583251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                validation_error_map[error_code]);
659f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis            } else if (mem_binding->binding.mem == MEMORY_UNBOUND) {
6603251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
6619b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                HandleToUint64(mem), __LINE__, MEMTRACK_REBIND_OBJECT, "MEM",
6623251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "In %s, attempting to bind memory (0x%" PRIxLEAST64 ") to object (0x%" PRIxLEAST64
6633251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                ") which was previous bound to memory that has since been freed. Memory bindings are immutable in "
6643251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "Vulkan so this attempt to bind to new memory is not allowed.",
6659b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                apiName, HandleToUint64(mem), handle);
6665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
6675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
6685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
6693251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
6705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
6715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
6725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// For NULL mem case, clear any previous binding Else...
6735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Make sure given object is in its object map
6745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis//  IF a previous binding existed, update binding
6755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis//  Add reference from objectInfo to memoryInfo
6765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis//  Add reference off of object's binding info
6770a1ce3dfd81c9f4efbe46f5ba5ddaea70bc4aa61Chris Forbes// Return VK_TRUE if addition is successful, VK_FALSE otherwise
678ece0e981ee4a5ad2572d146a89fc64d699d79f36Chris Forbesstatic bool SetSparseMemBinding(layer_data *dev_data, MEM_BINDING binding, uint64_t handle, VulkanObjectType type) {
6793251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = VK_FALSE;
6805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Handle NULL case separately, just clear previous binding & decrement reference
681f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis    if (binding.mem == VK_NULL_HANDLE) {
682f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis        // TODO : This should cause the range of the resource to be unbound according to spec
6835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    } else {
684f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis        BINDABLE *mem_binding = GetObjectMemBinding(dev_data, handle, type);
685f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis        assert(mem_binding);
686f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis        assert(mem_binding->sparse);
6879a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        DEVICE_MEM_INFO *mem_info = GetMemObjInfo(dev_data, binding.mem);
688f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis        if (mem_info) {
689f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis            mem_info->obj_bindings.insert({handle, type});
6902e415b757c1e43fda35311aad026af8d5c96681cTobin Ehlis            // Need to set mem binding for this object
691f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis            mem_binding->sparse_bindings.insert(binding);
6925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
6935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
6943251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
695caf05e0db4959ae196ab34b024f352d9c0326870Tobin Ehlis}
696caf05e0db4959ae196ab34b024f352d9c0326870Tobin Ehlis
6975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Check object status for selected flag state
69851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool validate_status(layer_data *dev_data, GLOBAL_CB_NODE *pNode, CBStatusFlags status_mask, VkFlags msg_flags,
6994f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes                            const char *fail_msg, UNIQUE_VALIDATION_ERROR_CODE const msg_code) {
7003d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis    if (!(pNode->status & status_mask)) {
7014f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes        char const *const message = validation_error_map[msg_code];
70251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis        return log_msg(dev_data->report_data, msg_flags, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
7039b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                       HandleToUint64(pNode->commandBuffer), __LINE__, msg_code, "DS", "command buffer object 0x%p: %s. %s.",
7049b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                       pNode->commandBuffer, fail_msg, message);
7055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
706e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    return false;
7075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
7085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
7095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Retrieve pipeline node ptr for given pipeline object
71051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic PIPELINE_STATE *getPipelineState(layer_data const *dev_data, VkPipeline pipeline) {
71151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    auto it = dev_data->pipelineMap.find(pipeline);
71251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    if (it == dev_data->pipelineMap.end()) {
713ea8349eeee76ae2859c10870fd8bd9e60309eb28Chris Forbes        return nullptr;
7145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
71563cddeb5593a0ead9ecd5f74d05f506b37d7ac66Chris Forbes    return it->second.get();
7165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
7175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
7189a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisRENDER_PASS_STATE *GetRenderPassState(layer_data const *dev_data, VkRenderPass renderpass) {
71951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    auto it = dev_data->renderPassMap.find(renderpass);
72051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    if (it == dev_data->renderPassMap.end()) {
72116387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes        return nullptr;
72216387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes    }
723fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes    return it->second.get();
72416387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes}
72516387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes
726e6852f66a1f1eb57097dbf98b8218104849fda0fTobin Ehlisstd::shared_ptr<RENDER_PASS_STATE> GetRenderPassStateSharedPtr(layer_data const *dev_data, VkRenderPass renderpass) {
727ba9be0cec36d930fc0d5a0cbfbc00b0df49b08e4Tobin Ehlis    auto it = dev_data->renderPassMap.find(renderpass);
728ba9be0cec36d930fc0d5a0cbfbc00b0df49b08e4Tobin Ehlis    if (it == dev_data->renderPassMap.end()) {
729ba9be0cec36d930fc0d5a0cbfbc00b0df49b08e4Tobin Ehlis        return nullptr;
730ba9be0cec36d930fc0d5a0cbfbc00b0df49b08e4Tobin Ehlis    }
731ba9be0cec36d930fc0d5a0cbfbc00b0df49b08e4Tobin Ehlis    return it->second;
732ba9be0cec36d930fc0d5a0cbfbc00b0df49b08e4Tobin Ehlis}
733ba9be0cec36d930fc0d5a0cbfbc00b0df49b08e4Tobin Ehlis
7349a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisFRAMEBUFFER_STATE *GetFramebufferState(const layer_data *dev_data, VkFramebuffer framebuffer) {
73551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    auto it = dev_data->frameBufferMap.find(framebuffer);
73651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    if (it == dev_data->frameBufferMap.end()) {
737f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes        return nullptr;
738f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes    }
73904861caca7eb93a5241b164e8480bb93c826902cTobin Ehlis    return it->second.get();
740f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes}
741f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes
7423f75ec6fa8700769a790d84e07c270579ded5468Tobin Ehlisstd::shared_ptr<cvdescriptorset::DescriptorSetLayout const> const GetDescriptorSetLayout(layer_data const *dev_data,
7433f75ec6fa8700769a790d84e07c270579ded5468Tobin Ehlis                                                                                         VkDescriptorSetLayout dsLayout) {
74451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    auto it = dev_data->descriptorSetLayoutMap.find(dsLayout);
74551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    if (it == dev_data->descriptorSetLayoutMap.end()) {
74611f1fde2721c198a619e4a22fff60eef9a16fae8Chris Forbes        return nullptr;
74711f1fde2721c198a619e4a22fff60eef9a16fae8Chris Forbes    }
748d34b2c191243c1646f1ccc2378262383e9ec1348Tobin Ehlis    return it->second;
74911f1fde2721c198a619e4a22fff60eef9a16fae8Chris Forbes}
75011f1fde2721c198a619e4a22fff60eef9a16fae8Chris Forbes
75151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic PIPELINE_LAYOUT_NODE const *getPipelineLayout(layer_data const *dev_data, VkPipelineLayout pipeLayout) {
75251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    auto it = dev_data->pipelineLayoutMap.find(pipeLayout);
75351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    if (it == dev_data->pipelineLayoutMap.end()) {
7544a45a42023b281f55953222c1a6c3e80f50e5f2aChris Forbes        return nullptr;
7554a45a42023b281f55953222c1a6c3e80f50e5f2aChris Forbes    }
7564a45a42023b281f55953222c1a6c3e80f50e5f2aChris Forbes    return &it->second;
7574a45a42023b281f55953222c1a6c3e80f50e5f2aChris Forbes}
7584a45a42023b281f55953222c1a6c3e80f50e5f2aChris Forbes
759d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbesshader_module const *GetShaderModuleState(layer_data const *dev_data, VkShaderModule module) {
760d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes    auto it = dev_data->shaderModuleMap.find(module);
761d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes    if (it == dev_data->shaderModuleMap.end()) {
762d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes        return nullptr;
763d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes    }
764d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes    return it->second.get();
765d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes}
766d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes
767e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves// Return true if for a given PSO, the given state enum is dynamic, else return false
7684c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlisstatic bool isDynamic(const PIPELINE_STATE *pPipeline, const VkDynamicState state) {
7695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pPipeline && pPipeline->graphicsPipelineCI.pDynamicState) {
7705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t i = 0; i < pPipeline->graphicsPipelineCI.pDynamicState->dynamicStateCount; i++) {
771cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            if (state == pPipeline->graphicsPipelineCI.pDynamicState->pDynamicStates[i]) return true;
7725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
7735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
774e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    return false;
7755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
7765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
7775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Validate state stored as flags at time of draw call
7784f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayesstatic bool validate_draw_state_flags(layer_data *dev_data, GLOBAL_CB_NODE *pCB, const PIPELINE_STATE *pPipe, bool indexed,
7794f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes                                      UNIQUE_VALIDATION_ERROR_CODE const msg_code) {
7809c4006684a13db43f0dbc8d0015a9ef34872ca09Chris Forbes    bool result = false;
781ca546210846c65808717f8875deae39bd227c240Tobin Ehlis    if (pPipe->graphicsPipelineCI.pInputAssemblyState &&
782ca546210846c65808717f8875deae39bd227c240Tobin Ehlis        ((pPipe->graphicsPipelineCI.pInputAssemblyState->topology == VK_PRIMITIVE_TOPOLOGY_LINE_LIST) ||
783ca546210846c65808717f8875deae39bd227c240Tobin Ehlis         (pPipe->graphicsPipelineCI.pInputAssemblyState->topology == VK_PRIMITIVE_TOPOLOGY_LINE_STRIP))) {
7843d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis        result |= validate_status(dev_data, pCB, CBSTATUS_LINE_WIDTH_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT,
7854f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes                                  "Dynamic line width state not set for this command buffer", msg_code);
7863d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis    }
78745824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves    if (pPipe->graphicsPipelineCI.pRasterizationState &&
78845824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves        (pPipe->graphicsPipelineCI.pRasterizationState->depthBiasEnable == VK_TRUE)) {
7893d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis        result |= validate_status(dev_data, pCB, CBSTATUS_DEPTH_BIAS_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT,
7904f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes                                  "Dynamic depth bias state not set for this command buffer", msg_code);
7913d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis    }
7923d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis    if (pPipe->blendConstantsEnabled) {
7933d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis        result |= validate_status(dev_data, pCB, CBSTATUS_BLEND_CONSTANTS_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT,
7944f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes                                  "Dynamic blend constants state not set for this command buffer", msg_code);
7953d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis    }
79645824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves    if (pPipe->graphicsPipelineCI.pDepthStencilState &&
79745824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves        (pPipe->graphicsPipelineCI.pDepthStencilState->depthBoundsTestEnable == VK_TRUE)) {
7983d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis        result |= validate_status(dev_data, pCB, CBSTATUS_DEPTH_BOUNDS_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT,
7994f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes                                  "Dynamic depth bounds state not set for this command buffer", msg_code);
8003d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis    }
80145824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves    if (pPipe->graphicsPipelineCI.pDepthStencilState &&
80245824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves        (pPipe->graphicsPipelineCI.pDepthStencilState->stencilTestEnable == VK_TRUE)) {
8033d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis        result |= validate_status(dev_data, pCB, CBSTATUS_STENCIL_READ_MASK_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT,
8044f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes                                  "Dynamic stencil read mask state not set for this command buffer", msg_code);
8053d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis        result |= validate_status(dev_data, pCB, CBSTATUS_STENCIL_WRITE_MASK_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT,
8064f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes                                  "Dynamic stencil write mask state not set for this command buffer", msg_code);
8073d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis        result |= validate_status(dev_data, pCB, CBSTATUS_STENCIL_REFERENCE_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT,
8084f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes                                  "Dynamic stencil reference state not set for this command buffer", msg_code);
8093d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis    }
8101c130ea631a82716dc7334de17767536525f2292Tobin Ehlis    if (indexed) {
8113d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis        result |= validate_status(dev_data, pCB, CBSTATUS_INDEX_BUFFER_BOUND, VK_DEBUG_REPORT_ERROR_BIT_EXT,
8124f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes                                  "Index buffer object not bound to this command buffer when Indexed Draw attempted", msg_code);
8133d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis    }
8144f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes
8155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
8165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
8175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
818b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlisstatic bool logInvalidAttachmentMessage(layer_data const *dev_data, const char *type1_string, const RENDER_PASS_STATE *rp1_state,
8199d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis                                        const char *type2_string, const RENDER_PASS_STATE *rp2_state, uint32_t primary_attach,
8209d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis                                        uint32_t secondary_attach, const char *msg, const char *caller,
8219d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis                                        UNIQUE_VALIDATION_ERROR_CODE error_code) {
8229d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis    return log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT,
8239d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis                   HandleToUint64(rp1_state->renderPass), __LINE__, error_code, "DS",
8249d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis                   "%s: RenderPasses incompatible between %s w/ renderPass 0x%" PRIx64 " and %s w/ renderPass 0x%" PRIx64
8259d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis                   " Attachment %u is not compatible with %u: %s. %s",
8269d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis                   caller, type1_string, HandleToUint64(rp1_state->renderPass), type2_string, HandleToUint64(rp2_state->renderPass),
8279d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis                   primary_attach, secondary_attach, msg, validation_error_map[error_code]);
8289d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis}
8299d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis
830b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlisstatic bool validateAttachmentCompatibility(layer_data const *dev_data, const char *type1_string,
831b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlis                                            const RENDER_PASS_STATE *rp1_state, const char *type2_string,
832b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlis                                            const RENDER_PASS_STATE *rp2_state, uint32_t primary_attach, uint32_t secondary_attach,
83311926a9087773a853b9b2cefbe80c17347cf36caTobin Ehlis                                            const char *caller, UNIQUE_VALIDATION_ERROR_CODE error_code) {
8349d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis    bool skip = false;
8359d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis    const auto &primaryPassCI = rp1_state->createInfo;
8369d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis    const auto &secondaryPassCI = rp2_state->createInfo;
8379d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis    if (primaryPassCI.attachmentCount <= primary_attach) {
8389d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis        primary_attach = VK_ATTACHMENT_UNUSED;
8399d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis    }
8409d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis    if (secondaryPassCI.attachmentCount <= secondary_attach) {
8419d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis        secondary_attach = VK_ATTACHMENT_UNUSED;
8429d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis    }
8439d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis    if (primary_attach == VK_ATTACHMENT_UNUSED && secondary_attach == VK_ATTACHMENT_UNUSED) {
8449d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis        return skip;
8459d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis    }
8469d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis    if (primary_attach == VK_ATTACHMENT_UNUSED) {
8479d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis        skip |= logInvalidAttachmentMessage(dev_data, type1_string, rp1_state, type2_string, rp2_state, primary_attach,
8489d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis                                            secondary_attach, "The first is unused while the second is not.", caller, error_code);
8499d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis        return skip;
8509d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis    }
8519d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis    if (secondary_attach == VK_ATTACHMENT_UNUSED) {
8529d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis        skip |= logInvalidAttachmentMessage(dev_data, type1_string, rp1_state, type2_string, rp2_state, primary_attach,
8539d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis                                            secondary_attach, "The second is unused while the first is not.", caller, error_code);
8549d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis        return skip;
8559d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis    }
8569d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis    if (primaryPassCI.pAttachments[primary_attach].format != secondaryPassCI.pAttachments[secondary_attach].format) {
8579d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis        skip |= logInvalidAttachmentMessage(dev_data, type1_string, rp1_state, type2_string, rp2_state, primary_attach,
8589d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis                                            secondary_attach, "They have different formats.", caller, error_code);
8599d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis    }
8609d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis    if (primaryPassCI.pAttachments[primary_attach].samples != secondaryPassCI.pAttachments[secondary_attach].samples) {
8619d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis        skip |= logInvalidAttachmentMessage(dev_data, type1_string, rp1_state, type2_string, rp2_state, primary_attach,
8629d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis                                            secondary_attach, "They have different samples.", caller, error_code);
8639d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis    }
86411926a9087773a853b9b2cefbe80c17347cf36caTobin Ehlis    if (primaryPassCI.pAttachments[primary_attach].flags != secondaryPassCI.pAttachments[secondary_attach].flags) {
8659d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis        skip |=
8669d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis            logInvalidAttachmentMessage(dev_data, type1_string, rp1_state, type2_string, rp2_state, primary_attach, secondary_attach,
8679d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis                                        "They have different flags.", caller, error_code);
8689d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis    }
8699d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis
8709d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis    return skip;
8719d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis}
8729d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis
873b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlisstatic bool validateSubpassCompatibility(layer_data const *dev_data, const char *type1_string, const RENDER_PASS_STATE *rp1_state,
8749d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis                                         const char *type2_string, const RENDER_PASS_STATE *rp2_state, const int subpass,
87511926a9087773a853b9b2cefbe80c17347cf36caTobin Ehlis                                         const char *caller, UNIQUE_VALIDATION_ERROR_CODE error_code) {
8769d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis    bool skip = false;
8779d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis    const auto &primary_desc = rp1_state->createInfo.pSubpasses[subpass];
8789d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis    const auto &secondary_desc = rp2_state->createInfo.pSubpasses[subpass];
8799d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis    uint32_t maxInputAttachmentCount = std::max(primary_desc.inputAttachmentCount, secondary_desc.inputAttachmentCount);
8809d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis    for (uint32_t i = 0; i < maxInputAttachmentCount; ++i) {
8819d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis        uint32_t primary_input_attach = VK_ATTACHMENT_UNUSED, secondary_input_attach = VK_ATTACHMENT_UNUSED;
8829d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis        if (i < primary_desc.inputAttachmentCount) {
8839d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis            primary_input_attach = primary_desc.pInputAttachments[i].attachment;
8849d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis        }
8859d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis        if (i < secondary_desc.inputAttachmentCount) {
8869d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis            secondary_input_attach = secondary_desc.pInputAttachments[i].attachment;
8879d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis        }
8889d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis        skip |= validateAttachmentCompatibility(dev_data, type1_string, rp1_state, type2_string, rp2_state, primary_input_attach,
88911926a9087773a853b9b2cefbe80c17347cf36caTobin Ehlis                                                secondary_input_attach, caller, error_code);
8909d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis    }
8919d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis    uint32_t maxColorAttachmentCount = std::max(primary_desc.colorAttachmentCount, secondary_desc.colorAttachmentCount);
8929d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis    for (uint32_t i = 0; i < maxColorAttachmentCount; ++i) {
8939d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis        uint32_t primary_color_attach = VK_ATTACHMENT_UNUSED, secondary_color_attach = VK_ATTACHMENT_UNUSED;
8949d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis        if (i < primary_desc.colorAttachmentCount) {
8959d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis            primary_color_attach = primary_desc.pColorAttachments[i].attachment;
8969d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis        }
8979d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis        if (i < secondary_desc.colorAttachmentCount) {
8989d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis            secondary_color_attach = secondary_desc.pColorAttachments[i].attachment;
8999d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis        }
9009d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis        skip |= validateAttachmentCompatibility(dev_data, type1_string, rp1_state, type2_string, rp2_state, primary_color_attach,
90111926a9087773a853b9b2cefbe80c17347cf36caTobin Ehlis                                                secondary_color_attach, caller, error_code);
9029d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis        uint32_t primary_resolve_attach = VK_ATTACHMENT_UNUSED, secondary_resolve_attach = VK_ATTACHMENT_UNUSED;
9039d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis        if (i < primary_desc.colorAttachmentCount && primary_desc.pResolveAttachments) {
9049d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis            primary_resolve_attach = primary_desc.pResolveAttachments[i].attachment;
9059d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis        }
9069d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis        if (i < secondary_desc.colorAttachmentCount && secondary_desc.pResolveAttachments) {
9079d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis            secondary_resolve_attach = secondary_desc.pResolveAttachments[i].attachment;
9089d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis        }
9099d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis        skip |= validateAttachmentCompatibility(dev_data, type1_string, rp1_state, type2_string, rp2_state, primary_resolve_attach,
91011926a9087773a853b9b2cefbe80c17347cf36caTobin Ehlis                                                secondary_resolve_attach, caller, error_code);
9119d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis    }
9129d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis    uint32_t primary_depthstencil_attach = VK_ATTACHMENT_UNUSED, secondary_depthstencil_attach = VK_ATTACHMENT_UNUSED;
9139d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis    if (primary_desc.pDepthStencilAttachment) {
9149d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis        primary_depthstencil_attach = primary_desc.pDepthStencilAttachment[0].attachment;
9159d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis    }
9169d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis    if (secondary_desc.pDepthStencilAttachment) {
9179d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis        secondary_depthstencil_attach = secondary_desc.pDepthStencilAttachment[0].attachment;
9189d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis    }
9199d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis    skip |= validateAttachmentCompatibility(dev_data, type1_string, rp1_state, type2_string, rp2_state, primary_depthstencil_attach,
92011926a9087773a853b9b2cefbe80c17347cf36caTobin Ehlis                                            secondary_depthstencil_attach, caller, error_code);
9219d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis    return skip;
9229d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis}
9239d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis
9249d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis// Verify that given renderPass CreateInfo for primary and secondary command buffers are compatible.
9259d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis//  This function deals directly with the CreateInfo, there are overloaded versions below that can take the renderPass handle and
9269d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis//  will then feed into this function
927b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlisstatic bool validateRenderPassCompatibility(layer_data const *dev_data, const char *type1_string,
928b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlis                                            const RENDER_PASS_STATE *rp1_state, const char *type2_string,
929b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlis                                            const RENDER_PASS_STATE *rp2_state, const char *caller,
9309d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis                                            UNIQUE_VALIDATION_ERROR_CODE error_code) {
9319d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis    bool skip = false;
9329d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis
9339d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis    if (rp1_state->createInfo.subpassCount != rp2_state->createInfo.subpassCount) {
9349d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis        skip |=
9359d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis            log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT,
9369d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis                    HandleToUint64(rp1_state->renderPass), __LINE__, error_code, "DS",
9379d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis                    "%s: RenderPasses incompatible between %s w/ renderPass 0x%" PRIx64
9389d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis                    " with a subpassCount of %u and %s w/ renderPass 0x%" PRIx64 " with a subpassCount of %u. %s",
9399d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis                    caller, type1_string, HandleToUint64(rp1_state->renderPass), rp1_state->createInfo.subpassCount, type2_string,
9409d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis                    HandleToUint64(rp2_state->renderPass), rp2_state->createInfo.subpassCount, validation_error_map[error_code]);
9419d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis    } else {
9429d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis        for (uint32_t i = 0; i < rp1_state->createInfo.subpassCount; ++i) {
94311926a9087773a853b9b2cefbe80c17347cf36caTobin Ehlis            skip |= validateSubpassCompatibility(dev_data, type1_string, rp1_state, type2_string, rp2_state, i, caller, error_code);
9449d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis        }
9459d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis    }
9469d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis    return skip;
9479d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis}
9489d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis
9495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Return Set node ptr for specified set or else NULL
9509a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehliscvdescriptorset::DescriptorSet *GetSetNode(const layer_data *dev_data, VkDescriptorSet set) {
95151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    auto set_it = dev_data->setMap.find(set);
95251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    if (set_it == dev_data->setMap.end()) {
9535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return NULL;
9545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
955104ab082916e41467ef60baaab7a5a8b2e02c59cTobin Ehlis    return set_it->second;
9565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
9575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
958eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young// For given pipeline, return number of MSAA samples, or one if MSAA disabled
9594c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlisstatic VkSampleCountFlagBits getNumSamples(PIPELINE_STATE const *pipe) {
960ea8349eeee76ae2859c10870fd8bd9e60309eb28Chris Forbes    if (pipe->graphicsPipelineCI.pMultisampleState != NULL &&
961ea8349eeee76ae2859c10870fd8bd9e60309eb28Chris Forbes        VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO == pipe->graphicsPipelineCI.pMultisampleState->sType) {
962eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young        return pipe->graphicsPipelineCI.pMultisampleState->rasterizationSamples;
963eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young    }
964eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young    return VK_SAMPLE_COUNT_1_BIT;
965eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young}
966eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young
967bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic void list_bits(std::ostream &s, uint32_t bits) {
968b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes    for (int i = 0; i < 32 && bits; i++) {
969b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes        if (bits & (1 << i)) {
970b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes            s << i;
971b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes            bits &= ~(1 << i);
972b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes            if (bits) {
973b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes                s << ",";
974b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes            }
975b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes        }
976b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes    }
977b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes}
978b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes
979eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young// Validate draw-time state related to the PSO
98051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool ValidatePipelineDrawtimeState(layer_data const *dev_data, LAST_BOUND_STATE const &state, const GLOBAL_CB_NODE *pCB,
981b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlis                                          CMD_TYPE cmd_type, PIPELINE_STATE const *pPipeline, const char *caller) {
9823251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
98329d196e071b2dc1db47702085469396f2b956820Chris Forbes
984d79335137b414d5f89284a9ab3e014beb4ada3ebMike Weiblen    // Verify vertex binding
98529d196e071b2dc1db47702085469396f2b956820Chris Forbes    if (pPipeline->vertexBindingDescriptions.size() > 0) {
98629d196e071b2dc1db47702085469396f2b956820Chris Forbes        for (size_t i = 0; i < pPipeline->vertexBindingDescriptions.size(); i++) {
987312129ec52e6249aa453e27e6be17a8dab1e98b8Tobin Ehlis            auto vertex_binding = pPipeline->vertexBindingDescriptions[i].binding;
988312129ec52e6249aa453e27e6be17a8dab1e98b8Tobin Ehlis            if ((pCB->currentDrawData.buffers.size() < (vertex_binding + 1)) ||
989312129ec52e6249aa453e27e6be17a8dab1e98b8Tobin Ehlis                (pCB->currentDrawData.buffers[vertex_binding] == VK_NULL_HANDLE)) {
9903251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |=
991df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
9929b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(pCB->commandBuffer), __LINE__, DRAWSTATE_VTX_INDEX_OUT_OF_BOUNDS, "DS",
993cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                            "The Pipeline State Object (0x%" PRIxLEAST64
994cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                            ") expects that this Command Buffer's vertex binding Index %u "
995cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                            "should be set via vkCmdBindVertexBuffers. This is because VkVertexInputBindingDescription struct "
996cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                            "at index " PRINTF_SIZE_T_SPECIFIER " of pVertexBindingDescriptions has a binding value of %u.",
9979b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(state.pipeline_state->pipeline), vertex_binding, i, vertex_binding);
99829d196e071b2dc1db47702085469396f2b956820Chris Forbes            }
99929d196e071b2dc1db47702085469396f2b956820Chris Forbes        }
100029d196e071b2dc1db47702085469396f2b956820Chris Forbes    } else {
100158b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis        if (!pCB->currentDrawData.buffers.empty() && !pCB->vertex_buffer_used) {
10023251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT,
10039b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, HandleToUint64(pCB->commandBuffer), __LINE__,
10049b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            DRAWSTATE_VTX_INDEX_OUT_OF_BOUNDS, "DS",
10053251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "Vertex buffers are bound to command buffer (0x%p"
10063251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            ") but no vertex buffers are attached to this Pipeline State Object (0x%" PRIxLEAST64 ").",
10079b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            pCB->commandBuffer, HandleToUint64(state.pipeline_state->pipeline));
100829d196e071b2dc1db47702085469396f2b956820Chris Forbes        }
100929d196e071b2dc1db47702085469396f2b956820Chris Forbes    }
101029d196e071b2dc1db47702085469396f2b956820Chris Forbes    // If Viewport or scissors are dynamic, verify that dynamic count matches PSO count.
101129d196e071b2dc1db47702085469396f2b956820Chris Forbes    // Skip check if rasterization is disabled or there is no viewport.
101229d196e071b2dc1db47702085469396f2b956820Chris Forbes    if ((!pPipeline->graphicsPipelineCI.pRasterizationState ||
101329d196e071b2dc1db47702085469396f2b956820Chris Forbes         (pPipeline->graphicsPipelineCI.pRasterizationState->rasterizerDiscardEnable == VK_FALSE)) &&
101429d196e071b2dc1db47702085469396f2b956820Chris Forbes        pPipeline->graphicsPipelineCI.pViewportState) {
101529d196e071b2dc1db47702085469396f2b956820Chris Forbes        bool dynViewport = isDynamic(pPipeline, VK_DYNAMIC_STATE_VIEWPORT);
101629d196e071b2dc1db47702085469396f2b956820Chris Forbes        bool dynScissor = isDynamic(pPipeline, VK_DYNAMIC_STATE_SCISSOR);
1017b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes
101829d196e071b2dc1db47702085469396f2b956820Chris Forbes        if (dynViewport) {
1019b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes            auto requiredViewportsMask = (1 << pPipeline->graphicsPipelineCI.pViewportState->viewportCount) - 1;
1020b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes            auto missingViewportMask = ~pCB->viewportMask & requiredViewportsMask;
1021b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes            if (missingViewportMask) {
1022b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes                std::stringstream ss;
1023b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes                ss << "Dynamic viewport(s) ";
1024b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes                list_bits(ss, missingViewportMask);
1025d79335137b414d5f89284a9ab3e014beb4ada3ebMike Weiblen                ss << " are used by pipeline state object, but were not provided via calls to vkCmdSetViewport().";
10263251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
10273251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                __LINE__, DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS", "%s", ss.str().c_str());
102829d196e071b2dc1db47702085469396f2b956820Chris Forbes            }
102929d196e071b2dc1db47702085469396f2b956820Chris Forbes        }
1030b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes
103129d196e071b2dc1db47702085469396f2b956820Chris Forbes        if (dynScissor) {
1032b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes            auto requiredScissorMask = (1 << pPipeline->graphicsPipelineCI.pViewportState->scissorCount) - 1;
1033b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes            auto missingScissorMask = ~pCB->scissorMask & requiredScissorMask;
1034b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes            if (missingScissorMask) {
1035b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes                std::stringstream ss;
1036b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes                ss << "Dynamic scissor(s) ";
1037b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes                list_bits(ss, missingScissorMask);
1038d79335137b414d5f89284a9ab3e014beb4ada3ebMike Weiblen                ss << " are used by pipeline state object, but were not provided via calls to vkCmdSetScissor().";
10393251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
10403251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                __LINE__, DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS", "%s", ss.str().c_str());
104129d196e071b2dc1db47702085469396f2b956820Chris Forbes            }
104229d196e071b2dc1db47702085469396f2b956820Chris Forbes        }
104329d196e071b2dc1db47702085469396f2b956820Chris Forbes    }
104429d196e071b2dc1db47702085469396f2b956820Chris Forbes
104529d196e071b2dc1db47702085469396f2b956820Chris Forbes    // Verify that any MSAA request in PSO matches sample# in bound FB
104629d196e071b2dc1db47702085469396f2b956820Chris Forbes    // Skip the check if rasterization is disabled.
104729d196e071b2dc1db47702085469396f2b956820Chris Forbes    if (!pPipeline->graphicsPipelineCI.pRasterizationState ||
104829d196e071b2dc1db47702085469396f2b956820Chris Forbes        (pPipeline->graphicsPipelineCI.pRasterizationState->rasterizerDiscardEnable == VK_FALSE)) {
104929d196e071b2dc1db47702085469396f2b956820Chris Forbes        VkSampleCountFlagBits pso_num_samples = getNumSamples(pPipeline);
105029d196e071b2dc1db47702085469396f2b956820Chris Forbes        if (pCB->activeRenderPass) {
1051fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes            auto const render_pass_info = pCB->activeRenderPass->createInfo.ptr();
105229d196e071b2dc1db47702085469396f2b956820Chris Forbes            const VkSubpassDescription *subpass_desc = &render_pass_info->pSubpasses[pCB->activeSubpass];
105329d196e071b2dc1db47702085469396f2b956820Chris Forbes            uint32_t i;
105476957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes            unsigned subpass_num_samples = 0;
10550a7ed0466d3d3c6c71be07d66c200482d9a9d073Chris Forbes
105629d196e071b2dc1db47702085469396f2b956820Chris Forbes            for (i = 0; i < subpass_desc->colorAttachmentCount; i++) {
105776957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes                auto attachment = subpass_desc->pColorAttachments[i].attachment;
105876957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes                if (attachment != VK_ATTACHMENT_UNUSED)
105976957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes                    subpass_num_samples |= (unsigned)render_pass_info->pAttachments[attachment].samples;
106029d196e071b2dc1db47702085469396f2b956820Chris Forbes            }
10610a7ed0466d3d3c6c71be07d66c200482d9a9d073Chris Forbes
106276957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes            if (subpass_desc->pDepthStencilAttachment &&
106376957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes                subpass_desc->pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) {
106476957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes                auto attachment = subpass_desc->pDepthStencilAttachment->attachment;
106576957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes                subpass_num_samples |= (unsigned)render_pass_info->pAttachments[attachment].samples;
106629d196e071b2dc1db47702085469396f2b956820Chris Forbes            }
1067eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young
1068497e33d6b0547f5dccca245a5b6777831fbb0de0Maciej Jesionowski            if (!dev_data->extensions.vk_amd_mixed_attachment_samples &&
1069497e33d6b0547f5dccca245a5b6777831fbb0de0Maciej Jesionowski                ((subpass_num_samples & static_cast<unsigned>(pso_num_samples)) != subpass_num_samples)) {
10703251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
10719b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                HandleToUint64(pPipeline->pipeline), __LINE__, DRAWSTATE_NUM_SAMPLES_MISMATCH, "DS",
10729b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                "Num samples mismatch! At draw-time in Pipeline (0x%" PRIxLEAST64
10739b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                ") with %u samples while current RenderPass (0x%" PRIxLEAST64 ") w/ %u samples!",
10749b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                HandleToUint64(pPipeline->pipeline), pso_num_samples,
10759b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                HandleToUint64(pCB->activeRenderPass->renderPass), subpass_num_samples);
1076eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young            }
107729d196e071b2dc1db47702085469396f2b956820Chris Forbes        } else {
10783251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
10799b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(pPipeline->pipeline), __LINE__, DRAWSTATE_NUM_SAMPLES_MISMATCH, "DS",
10803251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "No active render pass found at draw-time in Pipeline (0x%" PRIxLEAST64 ")!",
10819b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(pPipeline->pipeline));
1082eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young        }
1083eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young    }
1084528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis    // Verify that PSO creation renderPass is compatible with active renderPass
1085528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis    if (pCB->activeRenderPass) {
1086b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlis        // TODO: Move all of the error codes common across different Draws into a LUT accessed by cmd_type
1087b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlis        // TODO: AMD extension codes are included here, but actual function entrypoints are not yet intercepted
1088b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlis        // Error codes for renderpass and subpass mismatches
1089b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlis        auto rp_error = VALIDATION_ERROR_1a200366, sp_error = VALIDATION_ERROR_1a200368;
1090b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlis        switch (cmd_type) {
1091b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlis            case CMD_DRAWINDEXED:
1092b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlis                rp_error = VALIDATION_ERROR_1a40038c;
1093b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlis                sp_error = VALIDATION_ERROR_1a40038e;
1094b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlis                break;
1095b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlis            case CMD_DRAWINDIRECT:
1096b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlis                rp_error = VALIDATION_ERROR_1aa003be;
1097b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlis                sp_error = VALIDATION_ERROR_1aa003c0;
1098b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlis                break;
1099b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlis            case CMD_DRAWINDIRECTCOUNTAMD:
1100b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlis                rp_error = VALIDATION_ERROR_1ac003f6;
1101b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlis                sp_error = VALIDATION_ERROR_1ac003f8;
1102b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlis                break;
1103b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlis            case CMD_DRAWINDEXEDINDIRECT:
1104b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlis                rp_error = VALIDATION_ERROR_1a600426;
1105b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlis                sp_error = VALIDATION_ERROR_1a600428;
1106b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlis                break;
1107b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlis            case CMD_DRAWINDEXEDINDIRECTCOUNTAMD:
1108b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlis                rp_error = VALIDATION_ERROR_1a800460;
1109b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlis                sp_error = VALIDATION_ERROR_1a800462;
1110b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlis                break;
1111b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlis            default:
1112b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlis                assert(CMD_DRAW == cmd_type);
1113b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlis                break;
1114b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlis        }
1115528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis        std::string err_string;
1116cafebcdd40427a0713a3564dc8f39e47edbdb02fTobin Ehlis        if (pCB->activeRenderPass->renderPass != pPipeline->rp_state->renderPass) {
1117528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis            // renderPass that PSO was created with must be compatible with active renderPass that PSO is being used with
1118b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlis            skip |= validateRenderPassCompatibility(dev_data, "active render pass", pCB->activeRenderPass, "pipeline state object",
1119cafebcdd40427a0713a3564dc8f39e47edbdb02fTobin Ehlis                                                    pPipeline->rp_state.get(), caller, rp_error);
1120528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis        }
1121c307df2953e6b023531a6ef7fd11e3ee2f2c58b0Chris Forbes        if (pPipeline->graphicsPipelineCI.subpass != pCB->activeSubpass) {
11223251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1123b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlis                            HandleToUint64(pPipeline->pipeline), __LINE__, sp_error, "DS",
1124b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlis                            "Pipeline was built for subpass %u but used in subpass %u. %s", pPipeline->graphicsPipelineCI.subpass,
1125b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlis                            pCB->activeSubpass, validation_error_map[sp_error]);
1126c307df2953e6b023531a6ef7fd11e3ee2f2c58b0Chris Forbes        }
1127528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis    }
112829d196e071b2dc1db47702085469396f2b956820Chris Forbes
11293251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
1130eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young}
1131eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young
1132d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes// For given cvdescriptorset::DescriptorSet, verify that its Set is compatible w/ the setLayout corresponding to
1133d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes// pipelineLayout[layoutIndex]
1134d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbesstatic bool verify_set_layout_compatibility(const cvdescriptorset::DescriptorSet *descriptor_set,
1135d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes                                            PIPELINE_LAYOUT_NODE const *pipeline_layout, const uint32_t layoutIndex,
1136d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes                                            string &errorMsg) {
1137d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes    auto num_sets = pipeline_layout->set_layouts.size();
1138d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes    if (layoutIndex >= num_sets) {
1139d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes        stringstream errorStr;
1140d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes        errorStr << "VkPipelineLayout (" << pipeline_layout->layout << ") only contains " << num_sets
1141d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes                 << " setLayouts corresponding to sets 0-" << num_sets - 1 << ", but you're attempting to bind set to index "
1142d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes                 << layoutIndex;
1143d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes        errorMsg = errorStr.str();
1144d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes        return false;
1145d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes    }
11462d4a3c28bf95f00fa2aac7d07288f6faf22208abMark Lobodzinski    if (descriptor_set->IsPushDescriptor()) return true;
1147d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes    auto layout_node = pipeline_layout->set_layouts[layoutIndex];
114888224335ef7965e89477c393331ef5fa628a9335Tobin Ehlis    return descriptor_set->IsCompatible(layout_node.get(), &errorMsg);
1149d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes}
1150d7aee1a79b51b1a46cb4f3b0667c24f9416fdd64Chris Forbes
11515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Validate overall state at the time of a draw call
1152b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlisstatic bool ValidateDrawState(layer_data *dev_data, GLOBAL_CB_NODE *cb_node, CMD_TYPE cmd_type, const bool indexed,
11534f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes                              const VkPipelineBindPoint bind_point, const char *function,
11544f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes                              UNIQUE_VALIDATION_ERROR_CODE const msg_code) {
1155e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool result = false;
11561c130ea631a82716dc7334de17767536525f2292Tobin Ehlis    auto const &state = cb_node->lastBound[bind_point];
11574c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis    PIPELINE_STATE *pPipe = state.pipeline_state;
115822fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis    if (nullptr == pPipe) {
115922fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis        result |= log_msg(
1160df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski            dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
11619b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus            HandleToUint64(cb_node->commandBuffer), __LINE__, DRAWSTATE_INVALID_PIPELINE, "DS",
116222fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis            "At Draw/Dispatch time no valid VkPipeline is bound! This is illegal. Please bind one with vkCmdBindPipeline().");
116322fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis        // Early return as any further checks below will be busted w/o a pipeline
1164cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        if (result) return true;
116522fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis    }
11663d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis    // First check flag states
11671c130ea631a82716dc7334de17767536525f2292Tobin Ehlis    if (VK_PIPELINE_BIND_POINT_GRAPHICS == bind_point)
116851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis        result = validate_draw_state_flags(dev_data, cb_node, pPipe, indexed, msg_code);
11697a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis
11705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Now complete other state checks
117169b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis    if (VK_NULL_HANDLE != state.pipeline_layout.layout) {
117222fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis        string errorString;
117369b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis        auto pipeline_layout = pPipe->pipeline_layout;
1174169c4506062f06d6676eb4da3c9e0437d1d9d659Chris Forbes
11751c130ea631a82716dc7334de17767536525f2292Tobin Ehlis        for (const auto &set_binding_pair : pPipe->active_slots) {
11761c130ea631a82716dc7334de17767536525f2292Tobin Ehlis            uint32_t setIndex = set_binding_pair.first;
117722fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis            // If valid set is not bound throw an error
117822fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis            if ((state.boundDescriptorSets.size() <= setIndex) || (!state.boundDescriptorSets[setIndex])) {
11799b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                result |=
11809b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
11819b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(cb_node->commandBuffer), __LINE__, DRAWSTATE_DESCRIPTOR_SET_NOT_BOUND, "DS",
11829b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            "VkPipeline 0x%" PRIxLEAST64 " uses set #%u but that set is not bound.",
11839b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(pPipe->pipeline), setIndex);
118412b7fc342b53fbdd399aae4a85959e37685936acChris Forbes            } else if (!verify_set_layout_compatibility(state.boundDescriptorSets[setIndex], &pipeline_layout, setIndex,
118569b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis                                                        errorString)) {
118669b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis                // Set is bound but not compatible w/ overlapping pipeline_layout from PSO
118771511c5a10533c910bfe62c3bcf58e2a4054e7acTobin Ehlis                VkDescriptorSet setHandle = state.boundDescriptorSets[setIndex]->GetSet();
118822fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis                result |=
118951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
11909b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(setHandle), __LINE__, DRAWSTATE_PIPELINE_LAYOUTS_INCOMPATIBLE, "DS",
1191414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                            "VkDescriptorSet (0x%" PRIxLEAST64
1192414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                            ") bound as set #%u is not compatible with overlapping VkPipelineLayout 0x%" PRIxLEAST64 " due to: %s",
11939b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(setHandle), setIndex, HandleToUint64(pipeline_layout.layout), errorString.c_str());
1194cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            } else {  // Valid set is bound and layout compatible, validate that it's updated
119522fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis                // Pull the set node
11961c130ea631a82716dc7334de17767536525f2292Tobin Ehlis                cvdescriptorset::DescriptorSet *descriptor_set = state.boundDescriptorSets[setIndex];
11977433ab60c7ff16d37edb0f8b17b606ccd363e210Tobin Ehlis                // Validate the draw-time state for this descriptor set
11987433ab60c7ff16d37edb0f8b17b606ccd363e210Tobin Ehlis                std::string err_str;
11992d4a3c28bf95f00fa2aac7d07288f6faf22208abMark Lobodzinski                if (!descriptor_set->IsPushDescriptor() &&
12002d4a3c28bf95f00fa2aac7d07288f6faf22208abMark Lobodzinski                    !descriptor_set->ValidateDrawState(set_binding_pair.second, state.dynamicOffsets[setIndex], cb_node, function,
12010db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis                                                       &err_str)) {
12021c130ea631a82716dc7334de17767536525f2292Tobin Ehlis                    auto set = descriptor_set->GetSet();
12030db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis                    result |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
12049b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                      VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, HandleToUint64(set), __LINE__,
12059b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                      DRAWSTATE_DESCRIPTOR_SET_NOT_UPDATED, "DS",
12060db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis                                      "Descriptor set 0x%" PRIxLEAST64 " encountered the following validation error at %s time: %s",
12079b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                      HandleToUint64(set), function, err_str.c_str());
12087433ab60c7ff16d37edb0f8b17b606ccd363e210Tobin Ehlis                }
12095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
121022fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis        }
121122fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis    }
1212eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young
1213eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young    // Check general pipeline state that needs to be validated at drawtime
1214b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlis    if (VK_PIPELINE_BIND_POINT_GRAPHICS == bind_point)
1215b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlis        result |= ValidatePipelineDrawtimeState(dev_data, state, cb_node, cmd_type, pPipe, function);
1216eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young
12175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
12185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
12195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
122051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic void UpdateDrawState(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, const VkPipelineBindPoint bind_point) {
12211c130ea631a82716dc7334de17767536525f2292Tobin Ehlis    auto const &state = cb_state->lastBound[bind_point];
1222ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis    PIPELINE_STATE *pPipe = state.pipeline_state;
1223ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis    if (VK_NULL_HANDLE != state.pipeline_layout.layout) {
12241c130ea631a82716dc7334de17767536525f2292Tobin Ehlis        for (const auto &set_binding_pair : pPipe->active_slots) {
12251c130ea631a82716dc7334de17767536525f2292Tobin Ehlis            uint32_t setIndex = set_binding_pair.first;
1226ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis            // Pull the set node
12271c130ea631a82716dc7334de17767536525f2292Tobin Ehlis            cvdescriptorset::DescriptorSet *descriptor_set = state.boundDescriptorSets[setIndex];
12282d4a3c28bf95f00fa2aac7d07288f6faf22208abMark Lobodzinski            if (!descriptor_set->IsPushDescriptor()) {
12292d4a3c28bf95f00fa2aac7d07288f6faf22208abMark Lobodzinski                // Bind this set and its active descriptor resources to the command buffer
12302d4a3c28bf95f00fa2aac7d07288f6faf22208abMark Lobodzinski                descriptor_set->BindCommandBuffer(cb_state, set_binding_pair.second);
12312d4a3c28bf95f00fa2aac7d07288f6faf22208abMark Lobodzinski                // For given active slots record updated images & buffers
12322d4a3c28bf95f00fa2aac7d07288f6faf22208abMark Lobodzinski                descriptor_set->GetStorageUpdates(set_binding_pair.second, &cb_state->updateBuffers, &cb_state->updateImages);
12332d4a3c28bf95f00fa2aac7d07288f6faf22208abMark Lobodzinski            }
1234ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis        }
1235ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis    }
123658b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis    if (pPipe->vertexBindingDescriptions.size() > 0) {
123758b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis        cb_state->vertex_buffer_used = true;
123858b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis    }
1239ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis}
1240ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis
12413d67a6d0f5c42da03d838178741ef10928cd6397Chris Forbesstatic bool ValidatePipelineLocked(layer_data *dev_data, std::vector<std::unique_ptr<PIPELINE_STATE>> const &pPipelines, int pipelineIndex) {
12423251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
12435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
12443d67a6d0f5c42da03d838178741ef10928cd6397Chris Forbes    PIPELINE_STATE *pPipeline = pPipelines[pipelineIndex].get();
12455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
12465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // If create derivative bit is set, check that we've specified a base
12475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // pipeline correctly, and that the base pipeline was created to allow
12485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // derivatives.
12495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pPipeline->graphicsPipelineCI.flags & VK_PIPELINE_CREATE_DERIVATIVE_BIT) {
12504c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis        PIPELINE_STATE *pBasePipeline = nullptr;
12515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (!((pPipeline->graphicsPipelineCI.basePipelineHandle != VK_NULL_HANDLE) ^
12525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis              (pPipeline->graphicsPipelineCI.basePipelineIndex != -1))) {
1253315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis            // This check is a superset of VALIDATION_ERROR_096005a8 and VALIDATION_ERROR_096005aa
12543251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
12559b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(pPipeline->pipeline), __LINE__, DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS",
12569b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            "Invalid Pipeline CreateInfo: exactly one of base pipeline index and handle must be specified");
12575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else if (pPipeline->graphicsPipelineCI.basePipelineIndex != -1) {
12585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (pPipeline->graphicsPipelineCI.basePipelineIndex >= pipelineIndex) {
12593251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |=
1260df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1261315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_208005a0, "DS",
1262f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt                            "Invalid Pipeline CreateInfo: base pipeline must occur earlier in array than derivative pipeline. %s",
1263315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            validation_error_map[VALIDATION_ERROR_208005a0]);
12645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            } else {
12653d67a6d0f5c42da03d838178741ef10928cd6397Chris Forbes                pBasePipeline = pPipelines[pPipeline->graphicsPipelineCI.basePipelineIndex].get();
12665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
12675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else if (pPipeline->graphicsPipelineCI.basePipelineHandle != VK_NULL_HANDLE) {
126851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis            pBasePipeline = getPipelineState(dev_data, pPipeline->graphicsPipelineCI.basePipelineHandle);
12695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
12705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
12715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (pBasePipeline && !(pBasePipeline->graphicsPipelineCI.flags & VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT)) {
12723251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
12739b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(pPipeline->pipeline), __LINE__, DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS",
12749b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            "Invalid Pipeline CreateInfo: base pipeline does not allow derivatives.");
12755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
12765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
12775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
1278c3e70f769bd4aa0988652050444d57cab4925c16Chris Forbes    return skip;
1279c3e70f769bd4aa0988652050444d57cab4925c16Chris Forbes}
1280c3e70f769bd4aa0988652050444d57cab4925c16Chris Forbes
1281c3e70f769bd4aa0988652050444d57cab4925c16Chris Forbes// UNLOCKED pipeline validation. DO NOT lookup objects in the layer_data->* maps in this function.
12823d67a6d0f5c42da03d838178741ef10928cd6397Chris Forbesstatic bool ValidatePipelineUnlocked(layer_data *dev_data, std::vector<std::unique_ptr<PIPELINE_STATE>> const &pPipelines, int pipelineIndex) {
1283c3e70f769bd4aa0988652050444d57cab4925c16Chris Forbes    bool skip = false;
1284c3e70f769bd4aa0988652050444d57cab4925c16Chris Forbes
12853d67a6d0f5c42da03d838178741ef10928cd6397Chris Forbes    PIPELINE_STATE *pPipeline = pPipelines[pipelineIndex].get();
1286c3e70f769bd4aa0988652050444d57cab4925c16Chris Forbes
1287fa30cd33537b2773dae129822b4e7c654a027929Chris Forbes    // Ensure the subpass index is valid. If not, then validate_and_capture_pipeline_shader_state
1288fa30cd33537b2773dae129822b4e7c654a027929Chris Forbes    // produces nonsense errors that confuse users. Other layers should already
1289fa30cd33537b2773dae129822b4e7c654a027929Chris Forbes    // emit errors for renderpass being invalid.
1290146a87545e7b707b1dbddbd9cb8b41869ad402ccChris Forbes    auto subpass_desc = &pPipeline->render_pass_ci.pSubpasses[pPipeline->graphicsPipelineCI.subpass];
1291146a87545e7b707b1dbddbd9cb8b41869ad402ccChris Forbes    if (pPipeline->graphicsPipelineCI.subpass >= pPipeline->render_pass_ci.subpassCount) {
1292fa30cd33537b2773dae129822b4e7c654a027929Chris Forbes        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1293fa30cd33537b2773dae129822b4e7c654a027929Chris Forbes                        HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_096005ee, "DS",
1294fa30cd33537b2773dae129822b4e7c654a027929Chris Forbes                        "Invalid Pipeline CreateInfo State: Subpass index %u "
1295fa30cd33537b2773dae129822b4e7c654a027929Chris Forbes                            "is out of range for this renderpass (0..%u). %s",
1296146a87545e7b707b1dbddbd9cb8b41869ad402ccChris Forbes                        pPipeline->graphicsPipelineCI.subpass, pPipeline->render_pass_ci.subpassCount - 1,
1297fa30cd33537b2773dae129822b4e7c654a027929Chris Forbes                        validation_error_map[VALIDATION_ERROR_096005ee]);
1298146a87545e7b707b1dbddbd9cb8b41869ad402ccChris Forbes        subpass_desc = nullptr;
1299fa30cd33537b2773dae129822b4e7c654a027929Chris Forbes    }
1300fa30cd33537b2773dae129822b4e7c654a027929Chris Forbes
13015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pPipeline->graphicsPipelineCI.pColorBlendState != NULL) {
1302fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis        const safe_VkPipelineColorBlendStateCreateInfo *color_blend_state = pPipeline->graphicsPipelineCI.pColorBlendState;
1303fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis        if (color_blend_state->attachmentCount != subpass_desc->colorAttachmentCount) {
13043251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(
130551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis                dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1306315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_096005d4, "DS",
1307fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis                "vkCreateGraphicsPipelines(): Render pass (0x%" PRIxLEAST64
1308fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis                ") subpass %u has colorAttachmentCount of %u which doesn't match the pColorBlendState->attachmentCount of %u. %s",
1309cafebcdd40427a0713a3564dc8f39e47edbdb02fTobin Ehlis                HandleToUint64(pPipeline->rp_state->renderPass), pPipeline->graphicsPipelineCI.subpass,
1310fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis                subpass_desc->colorAttachmentCount, color_blend_state->attachmentCount,
1311315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                validation_error_map[VALIDATION_ERROR_096005d4]);
1312fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis        }
131351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis        if (!dev_data->enabled_features.independentBlend) {
13143d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis            if (pPipeline->attachments.size() > 1) {
131526c548826ff0f83d12c769b51e7d6f76d1265c0eChris Forbes                VkPipelineColorBlendAttachmentState *pAttachments = &pPipeline->attachments[0];
1316c7bd67f06427b08ba65cdf2dd529c8234beebdd5Mark Lobodzinski                for (size_t i = 1; i < pPipeline->attachments.size(); i++) {
131706811df0256552cd7da9d7297672af377463fc4aMark Mueller                    // Quoting the spec: "If [the independent blend] feature is not enabled, the VkPipelineColorBlendAttachmentState
131806811df0256552cd7da9d7297672af377463fc4aMark Mueller                    // settings for all color attachments must be identical." VkPipelineColorBlendAttachmentState contains
131906811df0256552cd7da9d7297672af377463fc4aMark Mueller                    // only attachment state, so memcmp is best suited for the comparison
132006811df0256552cd7da9d7297672af377463fc4aMark Mueller                    if (memcmp(static_cast<const void *>(pAttachments), static_cast<const void *>(&pAttachments[i]),
132106811df0256552cd7da9d7297672af377463fc4aMark Mueller                               sizeof(pAttachments[0]))) {
13223251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        skip |=
1323df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                            log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1324315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_0f4004ba, "DS",
1325df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                                    "Invalid Pipeline CreateInfo: If independent blend feature not "
1326df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                                    "enabled, all elements of pAttachments must be identical. %s",
1327315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    validation_error_map[VALIDATION_ERROR_0f4004ba]);
132806811df0256552cd7da9d7297672af377463fc4aMark Mueller                        break;
1329c7bd67f06427b08ba65cdf2dd529c8234beebdd5Mark Lobodzinski                    }
13305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
13315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
13325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
133351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis        if (!dev_data->enabled_features.logicOp && (pPipeline->graphicsPipelineCI.pColorBlendState->logicOpEnable != VK_FALSE)) {
13343251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |=
1335df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1336315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_0f4004bc, "DS",
1337f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt                        "Invalid Pipeline CreateInfo: If logic operations feature not enabled, logicOpEnable must be VK_FALSE. %s",
1338315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_0f4004bc]);
13395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
13405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
13415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
134259ae0ccadec962d9ca2cce7584fad6c57c1a4458Tobin Ehlis    if (validate_and_capture_pipeline_shader_state(dev_data, pPipeline)) {
13433251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip = true;
13445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
134552156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes    // Each shader's stage must be unique
134652156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes    if (pPipeline->duplicate_shaders) {
134752156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes        for (uint32_t stage = VK_SHADER_STAGE_VERTEX_BIT; stage & VK_SHADER_STAGE_ALL_GRAPHICS; stage <<= 1) {
134852156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes            if (pPipeline->duplicate_shaders & stage) {
13499b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
13509b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                HandleToUint64(pPipeline->pipeline), __LINE__, DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS",
13519b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                "Invalid Pipeline CreateInfo State: Multiple shaders provided for stage %s",
13529b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                string_VkShaderStageFlagBits(VkShaderStageFlagBits(stage)));
135352156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes            }
135452156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes        }
135552156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes    }
13565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // VS is required
13575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (!(pPipeline->active_shaders & VK_SHADER_STAGE_VERTEX_BIT)) {
1358315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1359315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_096005ae, "DS",
1360315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        "Invalid Pipeline CreateInfo State: Vertex Shader required. %s",
1361315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_096005ae]);
13625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
13635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Either both or neither TC/TE shaders should be defined
13643067e46adf202d2cc3ce1e06909dc7fadf0c8c3bCort Stratton    bool has_control = (pPipeline->active_shaders & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0;
13653067e46adf202d2cc3ce1e06909dc7fadf0c8c3bCort Stratton    bool has_eval = (pPipeline->active_shaders & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0;
13663067e46adf202d2cc3ce1e06909dc7fadf0c8c3bCort Stratton    if (has_control && !has_eval) {
13673251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1368315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_096005b2, "DS",
13693251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "Invalid Pipeline CreateInfo State: TE and TC shaders must be included or excluded as a pair. %s",
1370315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_096005b2]);
1371f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt    }
13723067e46adf202d2cc3ce1e06909dc7fadf0c8c3bCort Stratton    if (!has_control && has_eval) {
13733251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1374315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_096005b4, "DS",
13753251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "Invalid Pipeline CreateInfo State: TE and TC shaders must be included or excluded as a pair. %s",
1376315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_096005b4]);
13775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
13785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Compute shaders should be specified independent of Gfx shaders
1379f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt    if (pPipeline->active_shaders & VK_SHADER_STAGE_COMPUTE_BIT) {
13803251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1381315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_096005b0, "DS",
13823251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "Invalid Pipeline CreateInfo State: Do not specify Compute Shader for Gfx Pipeline. %s",
1383315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_096005b0]);
13845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
13855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // VK_PRIMITIVE_TOPOLOGY_PATCH_LIST primitive topology is only valid for tessellation pipelines.
13865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Mismatching primitive topology and tessellation fails graphics pipeline creation.
13873067e46adf202d2cc3ce1e06909dc7fadf0c8c3bCort Stratton    if (has_control && has_eval &&
1388ca546210846c65808717f8875deae39bd227c240Tobin Ehlis        (!pPipeline->graphicsPipelineCI.pInputAssemblyState ||
1389ca546210846c65808717f8875deae39bd227c240Tobin Ehlis         pPipeline->graphicsPipelineCI.pInputAssemblyState->topology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST)) {
13903251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1391315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_096005c0, "DS",
13923251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "Invalid Pipeline CreateInfo State: "
13933251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "VK_PRIMITIVE_TOPOLOGY_PATCH_LIST must be set as IA "
13943251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "topology for tessellation pipelines. %s",
1395315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_096005c0]);
13965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
1397ca546210846c65808717f8875deae39bd227c240Tobin Ehlis    if (pPipeline->graphicsPipelineCI.pInputAssemblyState &&
1398ca546210846c65808717f8875deae39bd227c240Tobin Ehlis        pPipeline->graphicsPipelineCI.pInputAssemblyState->topology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST) {
13993067e46adf202d2cc3ce1e06909dc7fadf0c8c3bCort Stratton        if (!has_control || !has_eval) {
14003251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1401315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_096005c2, "DS",
14023251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "Invalid Pipeline CreateInfo State: "
14033251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "VK_PRIMITIVE_TOPOLOGY_PATCH_LIST primitive "
14043251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "topology is only valid for tessellation pipelines. %s",
1405315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            validation_error_map[VALIDATION_ERROR_096005c2]);
14065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
14075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
1408f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt
14096b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen    // If a rasterization state is provided...
1410a27508babf63d50aea75883a3702979193c23683Mark Young    if (pPipeline->graphicsPipelineCI.pRasterizationState) {
141158c5552c73679f81f57a64a809f7d4d6d52f4ce3Mark Lobodzinski        if ((pPipeline->graphicsPipelineCI.pRasterizationState->depthClampEnable == VK_TRUE) &&
141258c5552c73679f81f57a64a809f7d4d6d52f4ce3Mark Lobodzinski            (!dev_data->enabled_features.depthClamp)) {
14133251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1414315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_1020061c, "DS",
14153251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "vkCreateGraphicsPipelines(): the depthClamp device feature is disabled: the depthClampEnable "
14163251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "member of the VkPipelineRasterizationStateCreateInfo structure must be set to VK_FALSE. %s",
1417315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            validation_error_map[VALIDATION_ERROR_1020061c]);
141858c5552c73679f81f57a64a809f7d4d6d52f4ce3Mark Lobodzinski        }
141958c5552c73679f81f57a64a809f7d4d6d52f4ce3Mark Lobodzinski
1420434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski        if (!isDynamic(pPipeline, VK_DYNAMIC_STATE_DEPTH_BIAS) &&
1421434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski            (pPipeline->graphicsPipelineCI.pRasterizationState->depthBiasClamp != 0.0) &&
1422434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski            (!dev_data->enabled_features.depthBiasClamp)) {
14233251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
14249b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(pPipeline->pipeline), __LINE__, DRAWSTATE_INVALID_FEATURE, "DS",
14253251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "vkCreateGraphicsPipelines(): the depthBiasClamp device feature is disabled: the depthBiasClamp "
14263251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "member of the VkPipelineRasterizationStateCreateInfo structure must be set to 0.0 unless the "
14273251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "VK_DYNAMIC_STATE_DEPTH_BIAS dynamic state is enabled");
1428434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski        }
1429434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski
14306b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen        // If rasterization is enabled...
14316b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen        if (pPipeline->graphicsPipelineCI.pRasterizationState->rasterizerDiscardEnable == VK_FALSE) {
1432148e8028deee2b4b00ccd4a69210897add328265Mark Lobodzinski            if ((pPipeline->graphicsPipelineCI.pMultisampleState->alphaToOneEnable == VK_TRUE) &&
1433148e8028deee2b4b00ccd4a69210897add328265Mark Lobodzinski                (!dev_data->enabled_features.alphaToOne)) {
14343251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1435315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_10000622, "DS",
14363251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "vkCreateGraphicsPipelines(): the alphaToOne device feature is disabled: the alphaToOneEnable "
14373251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "member of the VkPipelineMultisampleStateCreateInfo structure must be set to VK_FALSE. %s",
1438315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                validation_error_map[VALIDATION_ERROR_10000622]);
1439148e8028deee2b4b00ccd4a69210897add328265Mark Lobodzinski            }
1440148e8028deee2b4b00ccd4a69210897add328265Mark Lobodzinski
14416b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen            // If subpass uses a depth/stencil attachment, pDepthStencilState must be a pointer to a valid structure
14426b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen            if (subpass_desc && subpass_desc->pDepthStencilAttachment &&
14436b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen                subpass_desc->pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) {
14446b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen                if (!pPipeline->graphicsPipelineCI.pDepthStencilState) {
14453251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1446315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_096005e0, "DS",
14473251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    "Invalid Pipeline CreateInfo State: pDepthStencilState is NULL when rasterization is "
14483251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    "enabled and subpass uses a depth/stencil attachment. %s",
1449315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    validation_error_map[VALIDATION_ERROR_096005e0]);
14509580629edfc5154cc9e36974cca12966fbd748b9Mark Lobodzinski
14519580629edfc5154cc9e36974cca12966fbd748b9Mark Lobodzinski                } else if ((pPipeline->graphicsPipelineCI.pDepthStencilState->depthBoundsTestEnable == VK_TRUE) &&
14529580629edfc5154cc9e36974cca12966fbd748b9Mark Lobodzinski                           (!dev_data->enabled_features.depthBounds)) {
14533251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= log_msg(
1454df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                        dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
14559b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        HandleToUint64(pPipeline->pipeline), __LINE__, DRAWSTATE_INVALID_FEATURE, "DS",
14569580629edfc5154cc9e36974cca12966fbd748b9Mark Lobodzinski                        "vkCreateGraphicsPipelines(): the depthBounds device feature is disabled: the depthBoundsTestEnable "
14579580629edfc5154cc9e36974cca12966fbd748b9Mark Lobodzinski                        "member of the VkPipelineDepthStencilStateCreateInfo structure must be set to VK_FALSE.");
14586b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen                }
14595dcdd90e54199dfeb29938a3a03d998397c22664Chris Forbes            }
1460326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen
1461326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen            // If subpass uses color attachments, pColorBlendState must be valid pointer
1462326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen            if (subpass_desc) {
1463326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen                uint32_t color_attachment_count = 0;
1464326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen                for (uint32_t i = 0; i < subpass_desc->colorAttachmentCount; ++i) {
1465326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen                    if (subpass_desc->pColorAttachments[i].attachment != VK_ATTACHMENT_UNUSED) {
1466326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen                        ++color_attachment_count;
1467326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen                    }
1468326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen                }
1469326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen                if (color_attachment_count > 0 && pPipeline->graphicsPipelineCI.pColorBlendState == nullptr) {
14703251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1471315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_096005e2, "DS",
14723251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    "Invalid Pipeline CreateInfo State: pColorBlendState is NULL when rasterization is "
14733251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    "enabled and subpass uses color attachments. %s",
1474315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    validation_error_map[VALIDATION_ERROR_096005e2]);
1475326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen                }
1476326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen            }
14775dcdd90e54199dfeb29938a3a03d998397c22664Chris Forbes        }
14785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
14796b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen
1480740a9cdda3aa9cc7a4124184bd58146e6e99d772Chris Forbes    auto vi = pPipeline->graphicsPipelineCI.pVertexInputState;
1481740a9cdda3aa9cc7a4124184bd58146e6e99d772Chris Forbes    if (vi != NULL) {
1482740a9cdda3aa9cc7a4124184bd58146e6e99d772Chris Forbes        for (uint32_t j = 0; j < vi->vertexAttributeDescriptionCount; j++) {
1483740a9cdda3aa9cc7a4124184bd58146e6e99d772Chris Forbes            VkFormat format = vi->pVertexAttributeDescriptions[j].format;
1484740a9cdda3aa9cc7a4124184bd58146e6e99d772Chris Forbes            // Internal call to get format info.  Still goes through layers, could potentially go directly to ICD.
1485740a9cdda3aa9cc7a4124184bd58146e6e99d772Chris Forbes            VkFormatProperties properties;
1486740a9cdda3aa9cc7a4124184bd58146e6e99d772Chris Forbes            dev_data->instance_data->dispatch_table.GetPhysicalDeviceFormatProperties(dev_data->physical_device, format, &properties);
1487740a9cdda3aa9cc7a4124184bd58146e6e99d772Chris Forbes            if ((properties.bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) == 0) {
1488740a9cdda3aa9cc7a4124184bd58146e6e99d772Chris Forbes                skip |= log_msg(
1489740a9cdda3aa9cc7a4124184bd58146e6e99d772Chris Forbes                    dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
1490740a9cdda3aa9cc7a4124184bd58146e6e99d772Chris Forbes                    __LINE__, VALIDATION_ERROR_14a004de, "IMAGE",
1491740a9cdda3aa9cc7a4124184bd58146e6e99d772Chris Forbes                    "vkCreateGraphicsPipelines: pCreateInfo[%d].pVertexInputState->vertexAttributeDescriptions[%d].format "
1492740a9cdda3aa9cc7a4124184bd58146e6e99d772Chris Forbes                        "(%s) is not a supported vertex buffer format. %s",
1493740a9cdda3aa9cc7a4124184bd58146e6e99d772Chris Forbes                    pipelineIndex, j, string_VkFormat(format), validation_error_map[VALIDATION_ERROR_14a004de]);
1494740a9cdda3aa9cc7a4124184bd58146e6e99d772Chris Forbes            }
1495740a9cdda3aa9cc7a4124184bd58146e6e99d772Chris Forbes        }
1496740a9cdda3aa9cc7a4124184bd58146e6e99d772Chris Forbes    }
1497740a9cdda3aa9cc7a4124184bd58146e6e99d772Chris Forbes
1498497e33d6b0547f5dccca245a5b6777831fbb0de0Maciej Jesionowski    if (dev_data->extensions.vk_amd_mixed_attachment_samples) {
1499497e33d6b0547f5dccca245a5b6777831fbb0de0Maciej Jesionowski        VkSampleCountFlagBits max_sample_count = static_cast<VkSampleCountFlagBits>(0);
1500497e33d6b0547f5dccca245a5b6777831fbb0de0Maciej Jesionowski        for (uint32_t i = 0; i < subpass_desc->colorAttachmentCount; ++i) {
1501497e33d6b0547f5dccca245a5b6777831fbb0de0Maciej Jesionowski            if (subpass_desc->pColorAttachments[i].attachment != VK_ATTACHMENT_UNUSED) {
1502497e33d6b0547f5dccca245a5b6777831fbb0de0Maciej Jesionowski                max_sample_count = std::max(max_sample_count, pPipeline->render_pass_ci.pAttachments[subpass_desc->pColorAttachments[i].attachment].samples);
1503497e33d6b0547f5dccca245a5b6777831fbb0de0Maciej Jesionowski            }
1504497e33d6b0547f5dccca245a5b6777831fbb0de0Maciej Jesionowski        }
1505497e33d6b0547f5dccca245a5b6777831fbb0de0Maciej Jesionowski        if (subpass_desc->pDepthStencilAttachment && subpass_desc->pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) {
1506497e33d6b0547f5dccca245a5b6777831fbb0de0Maciej Jesionowski            max_sample_count = std::max(max_sample_count, pPipeline->render_pass_ci.pAttachments[subpass_desc->pDepthStencilAttachment->attachment].samples);
1507497e33d6b0547f5dccca245a5b6777831fbb0de0Maciej Jesionowski        }
1508497e33d6b0547f5dccca245a5b6777831fbb0de0Maciej Jesionowski        if (pPipeline->graphicsPipelineCI.pMultisampleState->rasterizationSamples != max_sample_count) {
1509497e33d6b0547f5dccca245a5b6777831fbb0de0Maciej Jesionowski            skip |=
1510497e33d6b0547f5dccca245a5b6777831fbb0de0Maciej Jesionowski                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
1511497e33d6b0547f5dccca245a5b6777831fbb0de0Maciej Jesionowski                        HandleToUint64(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_09600bc2, "DS",
1512497e33d6b0547f5dccca245a5b6777831fbb0de0Maciej Jesionowski                        "vkCreateGraphicsPipelines: pCreateInfo[%d].pMultisampleState->rasterizationSamples (%s) != max attachment samples (%s) "
1513497e33d6b0547f5dccca245a5b6777831fbb0de0Maciej Jesionowski                        "used in subpass %u. %s",
1514497e33d6b0547f5dccca245a5b6777831fbb0de0Maciej Jesionowski                        pipelineIndex, string_VkSampleCountFlagBits(pPipeline->graphicsPipelineCI.pMultisampleState->rasterizationSamples),
1515497e33d6b0547f5dccca245a5b6777831fbb0de0Maciej Jesionowski                        string_VkSampleCountFlagBits(max_sample_count), pPipeline->graphicsPipelineCI.subpass,
1516497e33d6b0547f5dccca245a5b6777831fbb0de0Maciej Jesionowski                        validation_error_map[VALIDATION_ERROR_09600bc2]);
1517497e33d6b0547f5dccca245a5b6777831fbb0de0Maciej Jesionowski        }
1518497e33d6b0547f5dccca245a5b6777831fbb0de0Maciej Jesionowski    }
1519497e33d6b0547f5dccca245a5b6777831fbb0de0Maciej Jesionowski
15203251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
15215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
15225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
15235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Block of code at start here specifically for managing/tracking DSs
15245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
15255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Return Pool node ptr for specified pool or else NULL
15269a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisDESCRIPTOR_POOL_STATE *GetDescriptorPoolState(const layer_data *dev_data, const VkDescriptorPool pool) {
1527bb7ea477706f90eb2a72887f652795bc79f60ddeTobin Ehlis    auto pool_it = dev_data->descriptorPoolMap.find(pool);
1528bb7ea477706f90eb2a72887f652795bc79f60ddeTobin Ehlis    if (pool_it == dev_data->descriptorPoolMap.end()) {
15295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return NULL;
15305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
1531bb7ea477706f90eb2a72887f652795bc79f60ddeTobin Ehlis    return pool_it->second;
15325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
15335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
15345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Validate that given set is valid and that it's not being used by an in-flight CmdBuffer
15355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// func_str is the name of the calling function
1536e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves// Return false if no errors occur
1537e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves// Return true if validation error occurs and callback returns true (to skip upcoming API call down the chain)
15380dcd0f7b37456e2e552d37094ba503c0d089b906Tobin Ehlisstatic bool validateIdleDescriptorSet(const layer_data *dev_data, VkDescriptorSet set, std::string func_str) {
1539cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.idle_descriptor_set) return false;
15403251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
15410dcd0f7b37456e2e552d37094ba503c0d089b906Tobin Ehlis    auto set_node = dev_data->setMap.find(set);
15420dcd0f7b37456e2e552d37094ba503c0d089b906Tobin Ehlis    if (set_node == dev_data->setMap.end()) {
15433251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
15449b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        HandleToUint64(set), __LINE__, DRAWSTATE_DOUBLE_DESTROY, "DS",
15453251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "Cannot call %s() on descriptor set 0x%" PRIxLEAST64 " that has not been allocated.", func_str.c_str(),
15469b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        HandleToUint64(set));
15475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    } else {
15481c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis        // TODO : This covers various error cases so should pass error enum into this function and use passed in enum here
15495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (set_node->second->in_use.load()) {
15503251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
1551315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(set), __LINE__, VALIDATION_ERROR_2860026a, "DS",
15523251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "Cannot call %s() on descriptor set 0x%" PRIxLEAST64 " that is in use by a command buffer. %s",
1553315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            func_str.c_str(), HandleToUint64(set), validation_error_map[VALIDATION_ERROR_2860026a]);
15545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
15555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
15563251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
15575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
1558f80bf38f4fb3f177b3e1be11b7b1c5edcdbf7d9bChris Forbes
1559e6651096ed8f07840447783c66827cc16d659a49Tobin Ehlis// Remove set from setMap and delete the set
15609dd448578d59cb5ce692e833ba230783b30f3550Tobin Ehlisstatic void freeDescriptorSet(layer_data *dev_data, cvdescriptorset::DescriptorSet *descriptor_set) {
15619dd448578d59cb5ce692e833ba230783b30f3550Tobin Ehlis    dev_data->setMap.erase(descriptor_set->GetSet());
15629dd448578d59cb5ce692e833ba230783b30f3550Tobin Ehlis    delete descriptor_set;
15639dd448578d59cb5ce692e833ba230783b30f3550Tobin Ehlis}
15645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Free all DS Pools including their Sets & related sub-structs
15655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// NOTE : Calls to this function should be wrapped in mutex
156651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic void deletePools(layer_data *dev_data) {
1567ee7e96d032744c1db89cab21362ac8ecad6eec5aGabríel Arthúr Pétursson    for (auto ii = dev_data->descriptorPoolMap.begin(); ii != dev_data->descriptorPoolMap.end();) {
1568c5f47f0a54e14c47d402aeabc6498d981ecda9ccTobin Ehlis        // Remove this pools' sets from setMap and delete them
1569ee7e96d032744c1db89cab21362ac8ecad6eec5aGabríel Arthúr Pétursson        for (auto ds : ii->second->sets) {
157051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis            freeDescriptorSet(dev_data, ds);
15715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
1572ee7e96d032744c1db89cab21362ac8ecad6eec5aGabríel Arthúr Pétursson        ii->second->sets.clear();
1573ee7e96d032744c1db89cab21362ac8ecad6eec5aGabríel Arthúr Pétursson        delete ii->second;
1574ee7e96d032744c1db89cab21362ac8ecad6eec5aGabríel Arthúr Pétursson        ii = dev_data->descriptorPoolMap.erase(ii);
15755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
15765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
15775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
157851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic void clearDescriptorPool(layer_data *dev_data, const VkDevice device, const VkDescriptorPool pool,
15795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                                VkDescriptorPoolResetFlags flags) {
15809a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    DESCRIPTOR_POOL_STATE *pPool = GetDescriptorPoolState(dev_data, pool);
1581de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis    // TODO: validate flags
1582de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis    // For every set off of this pool, clear it, remove from setMap, and free cvdescriptorset::DescriptorSet
1583de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis    for (auto ds : pPool->sets) {
158451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis        freeDescriptorSet(dev_data, ds);
1585de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis    }
1586de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis    pPool->sets.clear();
1587de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis    // Reset available count for each type and available sets for this pool
1588de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis    for (uint32_t i = 0; i < pPool->availableDescriptorTypeCount.size(); ++i) {
1589de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis        pPool->availableDescriptorTypeCount[i] = pPool->maxDescriptorTypeCount[i];
15905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
1591de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis    pPool->availableSets = pPool->maxSets;
15925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
15935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
15945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// For given CB object, fetch associated CB Node from map
15959a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisGLOBAL_CB_NODE *GetCBNode(layer_data const *dev_data, const VkCommandBuffer cb) {
159651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    auto it = dev_data->commandBufferMap.find(cb);
159751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    if (it == dev_data->commandBufferMap.end()) {
15985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return NULL;
15995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
16005121a8dcacb23766ba4455b4eea429f0a3d62099Chris Forbes    return it->second;
16015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
16025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
160329f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis// If a renderpass is active, verify that the given command type is appropriate for current subpass state
160429f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlisbool ValidateCmdSubpassState(const layer_data *dev_data, const GLOBAL_CB_NODE *pCB, const CMD_TYPE cmd_type) {
1605cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (!pCB->activeRenderPass) return false;
16063251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
1607d0d8e333806eaac08bdc87ddeff886dc2b0f09e7Tobin Ehlis    if (pCB->activeSubpassContents == VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS &&
1608d0d8e333806eaac08bdc87ddeff886dc2b0f09e7Tobin Ehlis        (cmd_type != CMD_EXECUTECOMMANDS && cmd_type != CMD_NEXTSUBPASS && cmd_type != CMD_ENDRENDERPASS)) {
16093251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
16109b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        HandleToUint64(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER, "DS",
16113251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "Commands cannot be called in a subpass using secondary command buffers.");
16125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    } else if (pCB->activeSubpassContents == VK_SUBPASS_CONTENTS_INLINE && cmd_type == CMD_EXECUTECOMMANDS) {
16133251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
16149b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        HandleToUint64(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER, "DS",
16153251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "vkCmdExecuteCommands() cannot be called in a subpass using inline commands.");
16165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
16173251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
16185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
16195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
1620e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlisbool ValidateCmdQueueFlags(layer_data *dev_data, const GLOBAL_CB_NODE *cb_node, const char *caller_name,
1621e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis                           VkQueueFlags required_flags, UNIQUE_VALIDATION_ERROR_CODE error_code) {
1622baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt    auto pool = GetCommandPoolNode(dev_data, cb_node->createInfo.commandPool);
1623baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt    if (pool) {
1624baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt        VkQueueFlags queue_flags = dev_data->phys_dev_properties.queue_family_properties[pool->queueFamilyIndex].queueFlags;
1625baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt        if (!(required_flags & queue_flags)) {
1626baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt            string required_flags_string;
1627baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt            for (auto flag : {VK_QUEUE_TRANSFER_BIT, VK_QUEUE_GRAPHICS_BIT, VK_QUEUE_COMPUTE_BIT}) {
1628baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt                if (flag & required_flags) {
1629baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt                    if (required_flags_string.size()) {
1630baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt                        required_flags_string += " or ";
1631baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt                    }
1632baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt                    required_flags_string += string_VkQueueFlagBits(flag);
1633baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt                }
1634baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt            }
1635baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt            return log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
16369b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                           HandleToUint64(cb_node->commandBuffer), __LINE__, error_code, "DS",
1637baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt                           "Cannot call %s on a command buffer allocated from a pool without %s capabilities. %s.", caller_name,
1638baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt                           required_flags_string.c_str(), validation_error_map[error_code]);
1639baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt        }
1640baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt    }
16415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return false;
16425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
16435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
1644d00947f5dcd29a4d8aab59e62f72df50444d2537Chris Forbesstatic char const * GetCauseStr(VK_OBJECT obj) {
1645d00947f5dcd29a4d8aab59e62f72df50444d2537Chris Forbes    if (obj.type == kVulkanObjectTypeDescriptorSet)
1646d00947f5dcd29a4d8aab59e62f72df50444d2537Chris Forbes        return "destroyed or updated";
1647d00947f5dcd29a4d8aab59e62f72df50444d2537Chris Forbes    if (obj.type == kVulkanObjectTypeCommandBuffer)
1648d00947f5dcd29a4d8aab59e62f72df50444d2537Chris Forbes        return "destroyed or rerecorded";
1649d00947f5dcd29a4d8aab59e62f72df50444d2537Chris Forbes    return "destroyed";
1650d00947f5dcd29a4d8aab59e62f72df50444d2537Chris Forbes}
1651d00947f5dcd29a4d8aab59e62f72df50444d2537Chris Forbes
1652e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlisstatic bool ReportInvalidCommandBuffer(layer_data *dev_data, const GLOBAL_CB_NODE *cb_state, const char *call_source) {
1653ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski    bool skip = false;
1654ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski    for (auto obj : cb_state->broken_bindings) {
16557a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski        const char *type_str = object_string[obj.type];
1656d00947f5dcd29a4d8aab59e62f72df50444d2537Chris Forbes        const char *cause_str = GetCauseStr(obj);
1657ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
16589b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        HandleToUint64(cb_state->commandBuffer), __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER, "DS",
1659ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski                        "You are adding %s to command buffer 0x%p that is invalid because bound %s 0x%" PRIxLEAST64 " was %s.",
1660ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski                        call_source, cb_state->commandBuffer, type_str, obj.handle, cause_str);
1661ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski    }
1662ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski    return skip;
1663ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski}
1664ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski
1665623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski// Validate the given command being added to the specified cmd buffer, flagging errors if CB is not in the recording state or if
1666623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski// there's an issue with the Cmd ordering
1667e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlisbool ValidateCmd(layer_data *dev_data, const GLOBAL_CB_NODE *cb_state, const CMD_TYPE cmd, const char *caller_name) {
166833f3623e8124c3a6081b60f68b9d39a19a5840aeChris Forbes    switch (cb_state->state) {
166933f3623e8124c3a6081b60f68b9d39a19a5840aeChris Forbes        case CB_RECORDING:
167033f3623e8124c3a6081b60f68b9d39a19a5840aeChris Forbes            return ValidateCmdSubpassState(dev_data, cb_state, cmd);
167133f3623e8124c3a6081b60f68b9d39a19a5840aeChris Forbes
167246daa701a01b92ae19e3ee9e661d677128fe7e6dChris Forbes        case CB_INVALID_COMPLETE:
167346daa701a01b92ae19e3ee9e661d677128fe7e6dChris Forbes        case CB_INVALID_INCOMPLETE:
167433f3623e8124c3a6081b60f68b9d39a19a5840aeChris Forbes            return ReportInvalidCommandBuffer(dev_data, cb_state, caller_name);
167533f3623e8124c3a6081b60f68b9d39a19a5840aeChris Forbes
167633f3623e8124c3a6081b60f68b9d39a19a5840aeChris Forbes        default:
167733f3623e8124c3a6081b60f68b9d39a19a5840aeChris Forbes            return log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
16789b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                           HandleToUint64(cb_state->commandBuffer), __LINE__, DRAWSTATE_NO_BEGIN_COMMAND_BUFFER, "DS",
167933f3623e8124c3a6081b60f68b9d39a19a5840aeChris Forbes                           "You must call vkBeginCommandBuffer() before this call to %s", caller_name);
16805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
16815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
168229f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis
16837e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis// For given object struct return a ptr of BASE_NODE type for its wrapping struct
16847e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin EhlisBASE_NODE *GetStateStructPtrFromObject(layer_data *dev_data, VK_OBJECT object_struct) {
16857e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis    BASE_NODE *base_ptr = nullptr;
16867e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis    switch (object_struct.type) {
1687ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes        case kVulkanObjectTypeDescriptorSet: {
16889a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            base_ptr = GetSetNode(dev_data, reinterpret_cast<VkDescriptorSet &>(object_struct.handle));
1689cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            break;
1690cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        }
1691ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes        case kVulkanObjectTypeSampler: {
16929a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            base_ptr = GetSamplerState(dev_data, reinterpret_cast<VkSampler &>(object_struct.handle));
1693cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            break;
1694cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        }
1695ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes        case kVulkanObjectTypeQueryPool: {
16969a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            base_ptr = GetQueryPoolNode(dev_data, reinterpret_cast<VkQueryPool &>(object_struct.handle));
1697cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            break;
1698cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        }
1699ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes        case kVulkanObjectTypePipeline: {
1700cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            base_ptr = getPipelineState(dev_data, reinterpret_cast<VkPipeline &>(object_struct.handle));
1701cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            break;
1702cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        }
1703ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes        case kVulkanObjectTypeBuffer: {
17049a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            base_ptr = GetBufferState(dev_data, reinterpret_cast<VkBuffer &>(object_struct.handle));
1705cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            break;
1706cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        }
1707ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes        case kVulkanObjectTypeBufferView: {
17089a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            base_ptr = GetBufferViewState(dev_data, reinterpret_cast<VkBufferView &>(object_struct.handle));
1709cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            break;
1710cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        }
1711ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes        case kVulkanObjectTypeImage: {
17129a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            base_ptr = GetImageState(dev_data, reinterpret_cast<VkImage &>(object_struct.handle));
1713cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            break;
1714cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        }
1715ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes        case kVulkanObjectTypeImageView: {
17169a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            base_ptr = GetImageViewState(dev_data, reinterpret_cast<VkImageView &>(object_struct.handle));
1717cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            break;
1718cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        }
1719ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes        case kVulkanObjectTypeEvent: {
17209a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            base_ptr = GetEventNode(dev_data, reinterpret_cast<VkEvent &>(object_struct.handle));
1721cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            break;
1722cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        }
1723ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes        case kVulkanObjectTypeDescriptorPool: {
17249a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            base_ptr = GetDescriptorPoolState(dev_data, reinterpret_cast<VkDescriptorPool &>(object_struct.handle));
1725cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            break;
1726cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        }
1727ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes        case kVulkanObjectTypeCommandPool: {
17289a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            base_ptr = GetCommandPoolNode(dev_data, reinterpret_cast<VkCommandPool &>(object_struct.handle));
1729cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            break;
1730cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        }
1731ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes        case kVulkanObjectTypeFramebuffer: {
17329a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            base_ptr = GetFramebufferState(dev_data, reinterpret_cast<VkFramebuffer &>(object_struct.handle));
1733cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            break;
1734cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        }
1735ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes        case kVulkanObjectTypeRenderPass: {
17369a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            base_ptr = GetRenderPassState(dev_data, reinterpret_cast<VkRenderPass &>(object_struct.handle));
1737cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            break;
1738cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        }
1739ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes        case kVulkanObjectTypeDeviceMemory: {
17409a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            base_ptr = GetMemObjInfo(dev_data, reinterpret_cast<VkDeviceMemory &>(object_struct.handle));
1741cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            break;
1742cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        }
1743cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        default:
1744cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            // TODO : Any other objects to be handled here?
1745cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            assert(0);
1746cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            break;
1747bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis    }
17487e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis    return base_ptr;
17497e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis}
17507e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis
17517e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis// Tie the VK_OBJECT to the cmd buffer which includes:
17527e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis//  Add object_binding to cmd buffer
17537e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis//  Add cb_binding to object
17547e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlisstatic void addCommandBufferBinding(std::unordered_set<GLOBAL_CB_NODE *> *cb_bindings, VK_OBJECT obj, GLOBAL_CB_NODE *cb_node) {
17557e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis    cb_bindings->insert(cb_node);
17567e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis    cb_node->object_bindings.insert(obj);
17577e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis}
17587e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis// For a given object, if cb_node is in that objects cb_bindings, remove cb_node
17597e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlisstatic void removeCommandBufferBinding(layer_data *dev_data, VK_OBJECT const *object, GLOBAL_CB_NODE *cb_node) {
17607e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis    BASE_NODE *base_obj = GetStateStructPtrFromObject(dev_data, *object);
1761cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (base_obj) base_obj->cb_bindings.erase(cb_node);
1762bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis}
17635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Reset the command buffer state
17645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis//  Maintain the createInfo and set state to CB_NEW, but clear all other state
17657cb00fa300f2563ae3e8eb506bca912c11216953John Zulaufstatic void ResetCommandBufferState(layer_data *dev_data, const VkCommandBuffer cb) {
1766400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis    GLOBAL_CB_NODE *pCB = dev_data->commandBufferMap[cb];
17675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
1768b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine        pCB->in_use.store(0);
17695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // Reset CB state (note that createInfo is not cleared)
17705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->commandBuffer = cb;
17715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        memset(&pCB->beginInfo, 0, sizeof(VkCommandBufferBeginInfo));
17725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        memset(&pCB->inheritanceInfo, 0, sizeof(VkCommandBufferInheritanceInfo));
1773b68b13ed4952bce61f6ebb0023542660c26b0562Chris Forbes        pCB->hasDrawCmd = false;
17745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->state = CB_NEW;
17755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->submitCount = 0;
17765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->status = 0;
177714494d322787d939bf6a9d3a03fc3938009592e0Chris Forbes        pCB->static_status = 0;
1778b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes        pCB->viewportMask = 0;
1779b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes        pCB->scissorMask = 0;
178093c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski
178172d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis        for (uint32_t i = 0; i < VK_PIPELINE_BIND_POINT_RANGE_SIZE; ++i) {
178272d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis            pCB->lastBound[i].reset();
178372d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis        }
178493c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski
17855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        memset(&pCB->activeRenderPassBeginInfo, 0, sizeof(pCB->activeRenderPassBeginInfo));
1786ee691f5c5fa87aac3750454d2bca2cb582e4e817Chris Forbes        pCB->activeRenderPass = nullptr;
17875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->activeSubpassContents = VK_SUBPASS_CONTENTS_INLINE;
17885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->activeSubpass = 0;
1789e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis        pCB->broken_bindings.clear();
17905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->waitedEvents.clear();
17915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->events.clear();
1792c7e6bc41aa9c6e5a677b138b9459b252cd3bedf2Mark Lobodzinski        pCB->writeEventsBeforeWait.clear();
17935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->waitedEventsBeforeQueryReset.clear();
17945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->queryToStateMap.clear();
17955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->activeQueries.clear();
17965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->startedQueries.clear();
17975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->imageLayoutMap.clear();
17985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->eventToStageMap.clear();
17995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->drawData.clear();
18005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->currentDrawData.buffers.clear();
180158b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis        pCB->vertex_buffer_used = false;
18025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->primaryCommandBuffer = VK_NULL_HANDLE;
18031a3660584634742a3297915c94768d73f360e794Chris Forbes        // If secondary, invalidate any primary command buffer that may call us.
18041a3660584634742a3297915c94768d73f360e794Chris Forbes        if (pCB->createInfo.level == VK_COMMAND_BUFFER_LEVEL_SECONDARY) {
18051a3660584634742a3297915c94768d73f360e794Chris Forbes            invalidateCommandBuffers(dev_data,
18061a3660584634742a3297915c94768d73f360e794Chris Forbes                                     pCB->linkedCommandBuffers,
18071a3660584634742a3297915c94768d73f360e794Chris Forbes                                     {HandleToUint64(cb), kVulkanObjectTypeCommandBuffer});
18081a3660584634742a3297915c94768d73f360e794Chris Forbes        }
18091a3660584634742a3297915c94768d73f360e794Chris Forbes
18101a3660584634742a3297915c94768d73f360e794Chris Forbes        // Remove reverse command buffer links.
18111a3660584634742a3297915c94768d73f360e794Chris Forbes        for (auto pSubCB : pCB->linkedCommandBuffers) {
18121a3660584634742a3297915c94768d73f360e794Chris Forbes            pSubCB->linkedCommandBuffers.erase(pCB);
18131a3660584634742a3297915c94768d73f360e794Chris Forbes        }
18141a3660584634742a3297915c94768d73f360e794Chris Forbes        pCB->linkedCommandBuffers.clear();
18157a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis        pCB->updateImages.clear();
18167a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis        pCB->updateBuffers.clear();
1817400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis        clear_cmd_buf_and_mem_references(dev_data, pCB);
1818d807198f24437c1b2478ff1d06a33ce4873a1451Tobin Ehlis        pCB->queue_submit_functions.clear();
181979fc00370d55e7cbfd4052b579120e64b0a1a4beTobin Ehlis        pCB->cmd_execute_commands_functions.clear();
1820b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine        pCB->eventUpdates.clear();
1821d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine        pCB->queryUpdates.clear();
182293c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski
1823bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis        // Remove object bindings
1824bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis        for (auto obj : pCB->object_bindings) {
1825bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis            removeCommandBufferBinding(dev_data, &obj, pCB);
1826bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis        }
1827a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis        pCB->object_bindings.clear();
182893c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski        // Remove this cmdBuffer's reference from each FrameBuffer's CB ref list
182993c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski        for (auto framebuffer : pCB->framebuffers) {
18309a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            auto fb_state = GetFramebufferState(dev_data, framebuffer);
1831cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            if (fb_state) fb_state->cb_bindings.erase(pCB);
183293c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski        }
183393c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski        pCB->framebuffers.clear();
18347003b38da5cc27a063af3c45080f3a35438283eeTobin Ehlis        pCB->activeFramebuffer = VK_NULL_HANDLE;
18355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
18365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
18375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
1838dd004f4889b468d675579c61aaf97136d882e1bcChris ForbesCBStatusFlags MakeStaticStateMask(VkPipelineDynamicStateCreateInfo const *ds) {
1839dd004f4889b468d675579c61aaf97136d882e1bcChris Forbes    // initially assume everything is static state
1840dd004f4889b468d675579c61aaf97136d882e1bcChris Forbes    CBStatusFlags flags = CBSTATUS_ALL_STATE_SET;
1841dd004f4889b468d675579c61aaf97136d882e1bcChris Forbes
1842dd004f4889b468d675579c61aaf97136d882e1bcChris Forbes    if (ds) {
1843dd004f4889b468d675579c61aaf97136d882e1bcChris Forbes        for (uint32_t i = 0; i < ds->dynamicStateCount; i++) {
1844dd004f4889b468d675579c61aaf97136d882e1bcChris Forbes            switch (ds->pDynamicStates[i]) {
1845cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                case VK_DYNAMIC_STATE_LINE_WIDTH:
1846dd004f4889b468d675579c61aaf97136d882e1bcChris Forbes                    flags &= ~CBSTATUS_LINE_WIDTH_SET;
1847cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                    break;
1848cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                case VK_DYNAMIC_STATE_DEPTH_BIAS:
1849dd004f4889b468d675579c61aaf97136d882e1bcChris Forbes                    flags &= ~CBSTATUS_DEPTH_BIAS_SET;
1850cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                    break;
1851cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                case VK_DYNAMIC_STATE_BLEND_CONSTANTS:
1852dd004f4889b468d675579c61aaf97136d882e1bcChris Forbes                    flags &= ~CBSTATUS_BLEND_CONSTANTS_SET;
1853cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                    break;
1854cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                case VK_DYNAMIC_STATE_DEPTH_BOUNDS:
1855dd004f4889b468d675579c61aaf97136d882e1bcChris Forbes                    flags &= ~CBSTATUS_DEPTH_BOUNDS_SET;
1856cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                    break;
1857cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                case VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK:
1858dd004f4889b468d675579c61aaf97136d882e1bcChris Forbes                    flags &= ~CBSTATUS_STENCIL_READ_MASK_SET;
1859cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                    break;
1860cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                case VK_DYNAMIC_STATE_STENCIL_WRITE_MASK:
1861dd004f4889b468d675579c61aaf97136d882e1bcChris Forbes                    flags &= ~CBSTATUS_STENCIL_WRITE_MASK_SET;
1862cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                    break;
1863cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                case VK_DYNAMIC_STATE_STENCIL_REFERENCE:
1864dd004f4889b468d675579c61aaf97136d882e1bcChris Forbes                    flags &= ~CBSTATUS_STENCIL_REFERENCE_SET;
1865cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                    break;
18663c81367b48899b9b1dbdf9813b8aa99f16ccb823Chris Forbes                case VK_DYNAMIC_STATE_SCISSOR:
18673c81367b48899b9b1dbdf9813b8aa99f16ccb823Chris Forbes                    flags &= ~CBSTATUS_SCISSOR_SET;
18683c81367b48899b9b1dbdf9813b8aa99f16ccb823Chris Forbes                    break;
18693c81367b48899b9b1dbdf9813b8aa99f16ccb823Chris Forbes                case VK_DYNAMIC_STATE_VIEWPORT:
18703c81367b48899b9b1dbdf9813b8aa99f16ccb823Chris Forbes                    flags &= ~CBSTATUS_VIEWPORT_SET;
18713c81367b48899b9b1dbdf9813b8aa99f16ccb823Chris Forbes                    break;
1872cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                default:
1873cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                    break;
18745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
18755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
18765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
1877dd004f4889b468d675579c61aaf97136d882e1bcChris Forbes
1878dd004f4889b468d675579c61aaf97136d882e1bcChris Forbes    return flags;
1879dd004f4889b468d675579c61aaf97136d882e1bcChris Forbes}
1880dd004f4889b468d675579c61aaf97136d882e1bcChris Forbes
1881623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski// Flags validation error if the associated call is made inside a render pass. The apiName routine should ONLY be called outside a
1882623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski// render pass.
1883e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlisbool insideRenderPass(const layer_data *dev_data, const GLOBAL_CB_NODE *pCB, const char *apiName,
1884e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis                      UNIQUE_VALIDATION_ERROR_CODE msgCode) {
1885e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool inside = false;
18865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB->activeRenderPass) {
188751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis        inside = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
18889b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                         HandleToUint64(pCB->commandBuffer), __LINE__, msgCode, "DS",
1889ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen                         "%s: It is invalid to issue this call inside an active render pass (0x%" PRIxLEAST64 "). %s", apiName,
18909b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                         HandleToUint64(pCB->activeRenderPass->renderPass), validation_error_map[msgCode]);
18915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
18925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return inside;
18935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
18945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
18955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Flags validation error if the associated call is made outside a render pass. The apiName
18965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// routine should ONLY be called inside a render pass.
189751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisbool outsideRenderPass(const layer_data *dev_data, GLOBAL_CB_NODE *pCB, const char *apiName, UNIQUE_VALIDATION_ERROR_CODE msgCode) {
1898e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool outside = false;
18995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (((pCB->createInfo.level == VK_COMMAND_BUFFER_LEVEL_PRIMARY) && (!pCB->activeRenderPass)) ||
19005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        ((pCB->createInfo.level == VK_COMMAND_BUFFER_LEVEL_SECONDARY) && (!pCB->activeRenderPass) &&
19015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis         !(pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT))) {
190251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis        outside = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
19039b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                          HandleToUint64(pCB->commandBuffer), __LINE__, msgCode, "DS",
1904ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen                          "%s: This call must be issued inside an active render pass. %s", apiName, validation_error_map[msgCode]);
19055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
19065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return outside;
19075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
19085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
1909f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbesstatic void init_core_validation(instance_layer_data *instance_data, const VkAllocationCallbacks *pAllocator) {
1910b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis    layer_debug_actions(instance_data->report_data, instance_data->logging_callback, pAllocator, "lunarg_core_validation");
19115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
19125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
19137a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis// For the given ValidationCheck enum, set all relevant instance disabled flags to true
1914b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulaufvoid SetDisabledFlags(instance_layer_data *instance_data, const VkValidationFlagsEXT *val_flags_struct) {
19157a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis    for (uint32_t i = 0; i < val_flags_struct->disabledValidationCheckCount; ++i) {
19167a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis        switch (val_flags_struct->pDisabledValidationChecks[i]) {
191759ae0ccadec962d9ca2cce7584fad6c57c1a4458Tobin Ehlis            case VK_VALIDATION_CHECK_SHADERS_EXT:
191859ae0ccadec962d9ca2cce7584fad6c57c1a4458Tobin Ehlis                instance_data->disabled.shader_validation = true;
191959ae0ccadec962d9ca2cce7584fad6c57c1a4458Tobin Ehlis                break;
19207a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis            case VK_VALIDATION_CHECK_ALL_EXT:
19217a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis                // Set all disabled flags to true
19227a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis                instance_data->disabled.SetAll(true);
19237a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis                break;
19247a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis            default:
19257a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis                break;
19267a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis        }
19277a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis    }
19287a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis}
19297a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis
1930bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
1931bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                              VkInstance *pInstance) {
19325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
19335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
19345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    assert(chain_info->u.pLayerInfo);
19355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
19365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
1937cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED;
19385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
19395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Advance the link info for the next element on the chain
19405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
19415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
19425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
1943cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (result != VK_SUCCESS) return result;
19445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
194556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(*pInstance), instance_layer_data_map);
194656a5ba3e60a723781945959ffc10e2e215350de5Chia-I Wu    instance_data->instance = *pInstance;
19479172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes    layer_init_instance_dispatch_table(*pInstance, &instance_data->dispatch_table, fpGetInstanceProcAddr);
19489172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes    instance_data->report_data = debug_report_create_instance(
19499172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes        &instance_data->dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount, pCreateInfo->ppEnabledExtensionNames);
19500cf009a4e2a5c22e4645f343c7a998f188a22015Chris Forbes    instance_data->extensions.InitFromInstanceCreateInfo(pCreateInfo);
1951b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis    init_core_validation(instance_data, pAllocator);
1952825ac70f99460ccb9494d34f93d8ee7ec303e5deMark Lobodzinski
19535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    ValidateLayerOrdering(*pCreateInfo);
19547a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis    // Parse any pNext chains
1955b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf    const auto *validation_flags_ext = lvl_find_in_chain<VkValidationFlagsEXT>(pCreateInfo->pNext);
1956b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf    if (validation_flags_ext) {
1957b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf        SetDisabledFlags(instance_data, validation_flags_ext);
19587a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis    }
19595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
19605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
19615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
19625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
196325002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// Hook DestroyInstance to remove tableInstanceMap entry
196489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
19655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // TODOSC : Shouldn't need any customization here
19665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    dispatch_key key = get_dispatch_key(instance);
19675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // TBD: Need any locking this early, in case this function is called at the
19685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // same time by more than one thread?
196956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    instance_layer_data *instance_data = GetLayerDataPtr(key, instance_layer_data_map);
19709172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes    instance_data->dispatch_table.DestroyInstance(instance, pAllocator);
19715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
1972ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    lock_guard_t lock(global_lock);
19735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Clean up logging callback, if any
19749172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes    while (instance_data->logging_callback.size() > 0) {
19759172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes        VkDebugReportCallbackEXT callback = instance_data->logging_callback.back();
19769172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes        layer_destroy_msg_callback(instance_data->report_data, callback, pAllocator);
19779172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes        instance_data->logging_callback.pop_back();
19785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
19795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
19809172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes    layer_debug_report_destroy_instance(instance_data->report_data);
1981d27b109eaf4da0a5514dc2ae2f3dd6a76976ba0dGabríel Arthúr Pétursson    FreeLayerDataPtr(key, instance_layer_data_map);
19825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
19835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
19845770f8ad21c40b2475201e73e9368a899b6886d0Petr Krausstatic bool ValidatePhysicalDeviceQueueFamily(instance_layer_data *instance_data, const PHYSICAL_DEVICE_STATE *pd_state,
19855770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                                              uint32_t requested_queue_family, int32_t err_code, const char *cmd_name,
19865770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                                              const char *queue_family_var_name, const char *vu_note = nullptr) {
19873251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
19885770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
19895770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    if (!vu_note) vu_note = validation_error_map[err_code];
19905770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
19915770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    const char *conditional_ext_cmd =
1992d4eaca34eca7f4b4e34190c441a579347bb2016aMark Lobodzinski        instance_data->extensions.vk_khr_get_physical_device_properties_2 ? "or vkGetPhysicalDeviceQueueFamilyProperties2KHR" : "";
19935770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
19945770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    std::string count_note = (UNCALLED == pd_state->vkGetPhysicalDeviceQueueFamilyPropertiesState)
19955770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                                 ? "the pQueueFamilyPropertyCount was never obtained"
19965770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                                 : "i.e. is not less than " + std::to_string(pd_state->queue_family_count);
19975770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
19985770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    if (requested_queue_family >= pd_state->queue_family_count) {
19993251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
20009b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        HandleToUint64(pd_state->phys_device), __LINE__, err_code, "DL",
20019b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        "%s: %s (= %" PRIu32
20029b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        ") is not less than any previously obtained pQueueFamilyPropertyCount from "
20035770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                        "vkGetPhysicalDeviceQueueFamilyProperties%s (%s). %s",
20045770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                        cmd_name, queue_family_var_name, requested_queue_family, conditional_ext_cmd, count_note.c_str(), vu_note);
20055770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    }
20065770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    return skip;
20075770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus}
20085770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
20095770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus// Verify VkDeviceQueueCreateInfos
20105770f8ad21c40b2475201e73e9368a899b6886d0Petr Krausstatic bool ValidateDeviceQueueCreateInfos(instance_layer_data *instance_data, const PHYSICAL_DEVICE_STATE *pd_state,
20115770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                                           uint32_t info_count, const VkDeviceQueueCreateInfo *infos) {
20125770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    bool skip = false;
20135770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
20145770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    for (uint32_t i = 0; i < info_count; ++i) {
20155770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus        const auto requested_queue_family = infos[i].queueFamilyIndex;
20165770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
20175770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus        // Verify that requested queue family is known to be valid at this point in time
20185770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus        std::string queue_family_var_name = "pCreateInfo->pQueueCreateInfos[" + std::to_string(i) + "].queueFamilyIndex";
2019315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= ValidatePhysicalDeviceQueueFamily(instance_data, pd_state, requested_queue_family, VALIDATION_ERROR_06c002fa,
20205770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                                                  "vkCreateDevice", queue_family_var_name.c_str());
20215770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
20225770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus        // Verify that requested  queue count of queue family is known to be valid at this point in time
20235770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus        if (requested_queue_family < pd_state->queue_family_count) {
20245770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus            const auto requested_queue_count = infos[i].queueCount;
20255770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus            const auto queue_family_props_count = pd_state->queue_family_properties.size();
20265770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus            const bool queue_family_has_props = requested_queue_family < queue_family_props_count;
2027d4eaca34eca7f4b4e34190c441a579347bb2016aMark Lobodzinski            const char *conditional_ext_cmd = instance_data->extensions.vk_khr_get_physical_device_properties_2
20285770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                                                  ? "or vkGetPhysicalDeviceQueueFamilyProperties2KHR"
20295770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                                                  : "";
20305770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus            std::string count_note =
20315770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                !queue_family_has_props
20325770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                    ? "the pQueueFamilyProperties[" + std::to_string(requested_queue_family) + "] was never obtained"
20335770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                    : "i.e. is not less than or equal to " +
20345770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                          std::to_string(pd_state->queue_family_properties[requested_queue_family].queueCount);
20355770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
20365770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus            if (!queue_family_has_props ||
20375770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                requested_queue_count > pd_state->queue_family_properties[requested_queue_family].queueCount) {
20383251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
20399b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, HandleToUint64(pd_state->phys_device), __LINE__,
2040315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                VALIDATION_ERROR_06c002fc, "DL",
20419b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                "vkCreateDevice: pCreateInfo->pQueueCreateInfos[%" PRIu32 "].queueCount (=%" PRIu32
20429b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                ") is not "
20435770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                                "less than or equal to available queue count for this "
20449b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                "pCreateInfo->pQueueCreateInfos[%" PRIu32 "].queueFamilyIndex} (=%" PRIu32
20459b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                ") obtained previously "
20465770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                                "from vkGetPhysicalDeviceQueueFamilyProperties%s (%s). %s",
20475770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                                i, requested_queue_count, i, requested_queue_family, conditional_ext_cmd, count_note.c_str(),
2048315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                validation_error_map[VALIDATION_ERROR_06c002fc]);
2049838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski            }
2050838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski        }
2051838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski    }
20525770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
20533251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
2054838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski}
2055838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski
2056f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski// Verify that features have been queried and that they are available
20575770f8ad21c40b2475201e73e9368a899b6886d0Petr Krausstatic bool ValidateRequestedFeatures(instance_layer_data *instance_data, const PHYSICAL_DEVICE_STATE *pd_state,
2058bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                      const VkPhysicalDeviceFeatures *requested_features) {
20593251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
2060f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski
20615770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    const VkBool32 *actual = reinterpret_cast<const VkBool32 *>(&pd_state->features);
2062825ac70f99460ccb9494d34f93d8ee7ec303e5deMark Lobodzinski    const VkBool32 *requested = reinterpret_cast<const VkBool32 *>(requested_features);
2063f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski    // TODO : This is a nice, compact way to loop through struct, but a bad way to report issues
2064f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski    //  Need to provide the struct member name with the issue. To do that seems like we'll
2065f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski    //  have to loop through each struct member which should be done w/ codegen to keep in synch.
2066f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski    uint32_t errors = 0;
2067f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski    uint32_t total_bools = sizeof(VkPhysicalDeviceFeatures) / sizeof(VkBool32);
2068f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski    for (uint32_t i = 0; i < total_bools; i++) {
2069f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski        if (requested[i] > actual[i]) {
20705770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus            skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
20715770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                            VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_INVALID_FEATURE_REQUESTED, "DL",
207291c2ca58e9ab21299931a4eadf03baf93118242bMark Lobodzinski                            "While calling vkCreateDevice(), requesting feature '%s' in VkPhysicalDeviceFeatures struct, "
20733251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "which is not available on this device.",
207491c2ca58e9ab21299931a4eadf03baf93118242bMark Lobodzinski                            GetPhysDevFeatureString(i));
2075f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski            errors++;
2076f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski        }
2077f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski    }
20785770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    if (errors && (UNCALLED == pd_state->vkGetPhysicalDeviceFeaturesState)) {
2079f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski        // If user didn't request features, notify them that they should
2080f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski        // TODO: Verify this against the spec. I believe this is an invalid use of the API and should return an error
20815770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus        skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
20825770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                        0, __LINE__, DEVLIMITS_INVALID_FEATURE_REQUESTED, "DL",
20833251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "You requested features that are unavailable on this device. You should first query feature "
20843251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "availability by calling vkGetPhysicalDeviceFeatures().");
2085f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski    }
20863251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
2087f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski}
2088f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski
208989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
209089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                            const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
20913251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
20925770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(gpu), instance_layer_data_map);
2093f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
2094ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
2095f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    auto pd_state = GetPhysicalDeviceState(instance_data, gpu);
2096f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
2097f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    // TODO: object_tracker should perhaps do this instead
2098f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    //       and it does not seem to currently work anyway -- the loader just crashes before this point
2099f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    if (!GetPhysicalDeviceState(instance_data, gpu)) {
2100f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus        skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
2101f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus                        0, __LINE__, DEVLIMITS_MUST_QUERY_COUNT, "DL",
2102f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus                        "Invalid call to vkCreateDevice() w/o first calling vkEnumeratePhysicalDevices().");
2103f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    }
2104f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski
2105f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski    // Check that any requested features are available
210656514e97bb296ac4612cae610a16cd46ac152dd8John Zulauf    // The enabled features can come from either pEnabledFeatures, or from the pNext chain
210756514e97bb296ac4612cae610a16cd46ac152dd8John Zulauf    const VkPhysicalDeviceFeatures *enabled_features_found = pCreateInfo->pEnabledFeatures;
210856514e97bb296ac4612cae610a16cd46ac152dd8John Zulauf    if (nullptr == enabled_features_found) {
2109b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf        const auto *features2 = lvl_find_in_chain<VkPhysicalDeviceFeatures2KHR>(pCreateInfo->pNext);
2110b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf        if (features2) {
2111b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf            enabled_features_found = &(features2->features);
211256514e97bb296ac4612cae610a16cd46ac152dd8John Zulauf        }
211356514e97bb296ac4612cae610a16cd46ac152dd8John Zulauf    }
211456514e97bb296ac4612cae610a16cd46ac152dd8John Zulauf
211556514e97bb296ac4612cae610a16cd46ac152dd8John Zulauf    if (enabled_features_found) {
211656514e97bb296ac4612cae610a16cd46ac152dd8John Zulauf        skip |= ValidateRequestedFeatures(instance_data, pd_state, enabled_features_found);
2117f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski    }
211856514e97bb296ac4612cae610a16cd46ac152dd8John Zulauf
21195770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    skip |=
21205770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus        ValidateDeviceQueueCreateInfos(instance_data, pd_state, pCreateInfo->queueCreateInfoCount, pCreateInfo->pQueueCreateInfos);
2121f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski
21225770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
21231d659b4113b77a95325df10d602a03f1e7abf8b7Mark Mueller
21245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
21255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
21265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    assert(chain_info->u.pLayerInfo);
21275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
21285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
212956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_data->instance, "vkCreateDevice");
21305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (fpCreateDevice == NULL) {
21315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return VK_ERROR_INITIALIZATION_FAILED;
21325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
21335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
21345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Advance the link info for the next element on the chain
21355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
21365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
21375770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    lock.unlock();
21385770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
21395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
21405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (result != VK_SUCCESS) {
21415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return result;
21425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
21435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
21445770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    lock.lock();
214556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *device_data = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
21465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
214756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    device_data->instance_data = instance_data;
21485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Setup device dispatch table
214956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_init_device_dispatch_table(*pDevice, &device_data->dispatch_table, fpGetDeviceProcAddr);
215056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    device_data->device = *pDevice;
2151ec85232c4d8d9ddf7d2ae57cb8203c5ab52c1106Mark Lobodzinski    // Save PhysicalDevice handle
215256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    device_data->physical_device = gpu;
21535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
215456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    device_data->report_data = layer_debug_report_create_device(instance_data->report_data, *pDevice);
2155a149f1a0cb39b48b19822c8cf9ef2426cd2251dfMark Lobodzinski    device_data->extensions.InitFromDeviceCreateInfo(&instance_data->extensions, pCreateInfo);
2156d4eaca34eca7f4b4e34190c441a579347bb2016aMark Lobodzinski
21575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Get physical device limits for this device
215856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    instance_data->dispatch_table.GetPhysicalDeviceProperties(gpu, &(device_data->phys_dev_properties.properties));
21595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    uint32_t count;
216056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    instance_data->dispatch_table.GetPhysicalDeviceQueueFamilyProperties(gpu, &count, nullptr);
216156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    device_data->phys_dev_properties.queue_family_properties.resize(count);
216256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    instance_data->dispatch_table.GetPhysicalDeviceQueueFamilyProperties(
216356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis        gpu, &count, &device_data->phys_dev_properties.queue_family_properties[0]);
21645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // TODO: device limits should make sure these are compatible
216556514e97bb296ac4612cae610a16cd46ac152dd8John Zulauf    if (enabled_features_found) {
216656514e97bb296ac4612cae610a16cd46ac152dd8John Zulauf        device_data->enabled_features = *enabled_features_found;
21675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    } else {
216856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis        memset(&device_data->enabled_features, 0, sizeof(VkPhysicalDeviceFeatures));
21695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
2170e47dbc3f3340fa177d877a67b2adb76a570027e5Mark Lobodzinski    // Store physical device properties and physical device mem limits into device layer_data structs
217156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    instance_data->dispatch_table.GetPhysicalDeviceMemoryProperties(gpu, &device_data->phys_dev_mem_props);
217256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    instance_data->dispatch_table.GetPhysicalDeviceProperties(gpu, &device_data->phys_dev_props);
2173b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
21745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
21755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    ValidateLayerOrdering(*pCreateInfo);
21765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
21775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
21785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
21795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
21805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// prototype
218189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
21825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // TODOSC : Shouldn't need any customization here
21835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    dispatch_key key = get_dispatch_key(device);
218456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(key, layer_data_map);
21855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Free all the memory
2186ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
218763cddeb5593a0ead9ecd5f74d05f506b37d7ac66Chris Forbes    dev_data->pipelineMap.clear();
2188fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes    dev_data->renderPassMap.clear();
21899b36ac77fbf55bd7ffdeb9020f2277fff3a5a807Chris Forbes    for (auto ii = dev_data->commandBufferMap.begin(); ii != dev_data->commandBufferMap.end(); ++ii) {
21909b36ac77fbf55bd7ffdeb9020f2277fff3a5a807Chris Forbes        delete (*ii).second;
21919b36ac77fbf55bd7ffdeb9020f2277fff3a5a807Chris Forbes    }
21929b36ac77fbf55bd7ffdeb9020f2277fff3a5a807Chris Forbes    dev_data->commandBufferMap.clear();
2193f13bee0887f3c3d1d597c82869864be3be836737Tobin Ehlis    // This will also delete all sets in the pool & remove them from setMap
21945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    deletePools(dev_data);
2195f13bee0887f3c3d1d597c82869864be3be836737Tobin Ehlis    // All sets should be removed
2196f13bee0887f3c3d1d597c82869864be3be836737Tobin Ehlis    assert(dev_data->setMap.empty());
2197fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis    dev_data->descriptorSetLayoutMap.clear();
21985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    dev_data->imageViewMap.clear();
21995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    dev_data->imageMap.clear();
22005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    dev_data->imageSubresourceMap.clear();
22015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    dev_data->imageLayoutMap.clear();
22025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    dev_data->bufferViewMap.clear();
22035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    dev_data->bufferMap.clear();
22041344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis    // Queues persist until device is destroyed
22051344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis    dev_data->queueMap.clear();
22065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Report any memory leaks
22075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    layer_debug_report_destroy_device(device);
2208b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
22095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
22105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#if DISPATCH_MAP_DEBUG
2211414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller    fprintf(stderr, "Device: 0x%p, key: 0x%p\n", device, key);
22125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#endif
2213d27b109eaf4da0a5514dc2ae2f3dd6a76976ba0dGabríel Arthúr Pétursson
2214d27b109eaf4da0a5514dc2ae2f3dd6a76976ba0dGabríel Arthúr Pétursson    dev_data->dispatch_table.DestroyDevice(device, pAllocator);
2215d27b109eaf4da0a5514dc2ae2f3dd6a76976ba0dGabríel Arthúr Pétursson    FreeLayerDataPtr(key, layer_data_map);
22165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
22175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
22185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
22195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2220208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis// For given stage mask, if Geometry shader stage is on w/o GS being enabled, report geo_error_id
2221208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis//   and if Tessellation Control or Evaluation shader stages are on w/o TS being enabled, report tess_error_id
2222208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlisstatic bool ValidateStageMaskGsTsEnables(layer_data *dev_data, VkPipelineStageFlags stageMask, const char *caller,
2223208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis                                         UNIQUE_VALIDATION_ERROR_CODE geo_error_id, UNIQUE_VALIDATION_ERROR_CODE tess_error_id) {
2224208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis    bool skip = false;
2225208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis    if (!dev_data->enabled_features.geometryShader && (stageMask & VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT)) {
2226208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
2227cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                        geo_error_id, "DL",
2228cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                        "%s call includes a stageMask with VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT bit set when "
2229cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                        "device does not have geometryShader feature enabled. %s",
2230208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis                        caller, validation_error_map[geo_error_id]);
2231208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis    }
2232208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis    if (!dev_data->enabled_features.tessellationShader &&
2233208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis        (stageMask & (VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT | VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT))) {
2234208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
2235cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                        tess_error_id, "DL",
2236cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                        "%s call includes a stageMask with VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT "
2237cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                        "and/or VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT bit(s) set when device "
2238cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                        "does not have tessellationShader feature enabled. %s",
2239208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis                        caller, validation_error_map[tess_error_id]);
2240208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis    }
2241208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis    return skip;
2242208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis}
2243208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis
2244ad97d033b614e6265aaa8c8f0d21a044982d4de7Jeremy Hayes// Loop through bound objects and increment their in_use counts.
2245ad97d033b614e6265aaa8c8f0d21a044982d4de7Jeremy Hayesstatic void IncrementBoundObjects(layer_data *dev_data, GLOBAL_CB_NODE const *cb_node) {
2246a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis    for (auto obj : cb_node->object_bindings) {
2247a317e7593a0fe227635fc8241908471acb36c952Chris Forbes        auto base_obj = GetStateStructPtrFromObject(dev_data, obj);
2248ad97d033b614e6265aaa8c8f0d21a044982d4de7Jeremy Hayes        if (base_obj) {
224951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour            base_obj->in_use.fetch_add(1);
2250162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis        }
2251a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis    }
2252a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis}
22535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Track which resources are in-flight by atomically incrementing their "in_use" count
225451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourstatic void incrementResources(layer_data *dev_data, GLOBAL_CB_NODE *cb_node) {
225551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    cb_node->submitCount++;
22569a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis    cb_node->in_use.fetch_add(1);
2257a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes
2258a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis    // First Increment for all "generic" objects bound to cmd buffer, followed by special-case objects below
2259ad97d033b614e6265aaa8c8f0d21a044982d4de7Jeremy Hayes    IncrementBoundObjects(dev_data, cb_node);
2260a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis    // TODO : We should be able to remove the NULL look-up checks from the code below as long as
2261a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis    //  all the corresponding cases are verified to cause CB_INVALID state and the CB_INVALID state
2262a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis    //  should then be flagged prior to calling this function
22639a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis    for (auto drawDataElement : cb_node->drawData) {
22645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (auto buffer : drawDataElement.buffers) {
22659a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            auto buffer_state = GetBufferState(dev_data, buffer);
226651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour            if (buffer_state) {
22675cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis                buffer_state->in_use.fetch_add(1);
22685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
22695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
22705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
22719a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis    for (auto event : cb_node->writeEventsBeforeWait) {
22729a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto event_state = GetEventNode(dev_data, event);
2273cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        if (event_state) event_state->write_in_use++;
2274c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine    }
22755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
22765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2277b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis// Note: This function assumes that the global lock is held by the calling thread.
2278b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis// For the given queue, verify the queue state up to the given seq number.
2279b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis// Currently the only check is to make sure that if there are events to be waited on prior to
2280b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis//  a QueryReset, make sure that all such events have been signalled.
2281d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbesstatic bool VerifyQueueStateToSeq(layer_data *dev_data, QUEUE_STATE *initial_queue, uint64_t initial_seq) {
2282b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis    bool skip = false;
2283d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes
2284d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes    // sequence number we want to validate up to, per queue
2285d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes    std::unordered_map<QUEUE_STATE *, uint64_t> target_seqs { { initial_queue, initial_seq } };
2286d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes    // sequence number we've completed validation for, per queue
2287d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes    std::unordered_map<QUEUE_STATE *, uint64_t> done_seqs;
2288d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes    std::vector<QUEUE_STATE *> worklist { initial_queue };
2289d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes
2290d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes    while (worklist.size()) {
2291d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes        auto queue = worklist.back();
2292d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes        worklist.pop_back();
2293d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes
2294d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes        auto target_seq = target_seqs[queue];
2295d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes        auto seq = std::max(done_seqs[queue], queue->seq);
2296d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes        auto sub_it = queue->submissions.begin() + int(seq - queue->seq);  // seq >= queue->seq
2297d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes
2298d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes        for (; seq < target_seq; ++sub_it, ++seq) {
2299d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes            for (auto &wait : sub_it->waitSemaphores) {
2300d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes                auto other_queue = GetQueueState(dev_data, wait.queue);
2301d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes
2302d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes                if (other_queue == queue)
2303d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes                    continue;   // semaphores /always/ point backwards, so no point here.
2304d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes
2305d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes                auto other_target_seq = std::max(target_seqs[other_queue], wait.seq);
2306d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes                auto other_done_seq = std::max(done_seqs[other_queue], other_queue->seq);
2307d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes
2308d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes                // if this wait is for another queue, and covers new sequence
2309d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes                // numbers beyond what we've already validated, mark the new
2310d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes                // target seq and (possibly-re)add the queue to the worklist.
2311d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes                if (other_done_seq < other_target_seq) {
2312d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes                    target_seqs[other_queue] = other_target_seq;
2313d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes                    worklist.push_back(other_queue);
2314d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes                }
2315d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes            }
2316d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes
2317d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes            for (auto cb : sub_it->cbs) {
2318d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes                auto cb_node = GetCBNode(dev_data, cb);
2319d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes                if (cb_node) {
2320d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes                    for (auto queryEventsPair : cb_node->waitedEventsBeforeQueryReset) {
2321d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes                        for (auto event : queryEventsPair.second) {
2322d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes                            if (dev_data->eventMap[event].needsSignaled) {
2323d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes                                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
2324d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes                                                VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, 0, DRAWSTATE_INVALID_QUERY, "DS",
2325d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes                                                "Cannot get query results on queryPool 0x%" PRIx64
2326d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes                                                " with index %d which was guarded by unsignaled event 0x%" PRIx64 ".",
23279b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                                HandleToUint64(queryEventsPair.first.pool), queryEventsPair.first.index,
23289b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                                HandleToUint64(event));
2329d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes                            }
2330b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis                        }
2331b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis                    }
2332b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine                }
2333b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine            }
2334b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine        }
2335d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes
2336d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes        // finally mark the point we've now validated this queue to.
2337d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes        done_seqs[queue] = seq;
233892b1701c552e96e96fdbbb77e4b106a9526f3b8cTobin Ehlis    }
2339d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes
2340b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis    return skip;
2341b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis}
2342b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis
2343b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis// When the given fence is retired, verify outstanding queue operations through the point of the fence
2344b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlisstatic bool VerifyQueueStateToFence(layer_data *dev_data, VkFence fence) {
23459a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto fence_state = GetFenceNode(dev_data, fence);
2346804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt    if (fence_state->scope == kSyncScopeInternal && VK_NULL_HANDLE != fence_state->signaler.first) {
23479a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        return VerifyQueueStateToSeq(dev_data, GetQueueState(dev_data, fence_state->signaler.first), fence_state->signaler.second);
2348b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis    }
2349b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis    return false;
2350b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine}
23517d33205c3aa4aba751a2c07f956634aac616f916Chris Forbes
2352a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis// Decrement in-use count for objects bound to command buffer
23532f8cbf3b166e175174877a59929902e005953d6dTobin Ehlisstatic void DecrementBoundResources(layer_data *dev_data, GLOBAL_CB_NODE const *cb_node) {
235400e8ce2e6c1c191758f7b7c15eeaf350e5b4a3b6Tobin Ehlis    BASE_NODE *base_obj = nullptr;
2355a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis    for (auto obj : cb_node->object_bindings) {
23567e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis        base_obj = GetStateStructPtrFromObject(dev_data, obj);
235700e8ce2e6c1c191758f7b7c15eeaf350e5b4a3b6Tobin Ehlis        if (base_obj) {
235800e8ce2e6c1c191758f7b7c15eeaf350e5b4a3b6Tobin Ehlis            base_obj->in_use.fetch_sub(1);
235900e8ce2e6c1c191758f7b7c15eeaf350e5b4a3b6Tobin Ehlis        }
2360a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis    }
2361a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis}
2362da8f07baf262972eb3e719fa07b073c180dff157Chris Forbes
236336c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlisstatic void RetireWorkOnQueue(layer_data *dev_data, QUEUE_STATE *pQueue, uint64_t seq) {
23649867daedbf52debc77d6568162ee21e071699b80Chris Forbes    std::unordered_map<VkQueue, uint64_t> otherQueueSeqs;
23659867daedbf52debc77d6568162ee21e071699b80Chris Forbes
23669867daedbf52debc77d6568162ee21e071699b80Chris Forbes    // Roll this queue forward, one submission at a time.
23679867daedbf52debc77d6568162ee21e071699b80Chris Forbes    while (pQueue->seq < seq) {
2368bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        auto &submission = pQueue->submissions.front();
23699867daedbf52debc77d6568162ee21e071699b80Chris Forbes
2370bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        for (auto &wait : submission.waitSemaphores) {
23719a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            auto pSemaphore = GetSemaphoreNode(dev_data, wait.semaphore);
2372c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski            if (pSemaphore) {
2373c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski                pSemaphore->in_use.fetch_sub(1);
2374c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski            }
2375bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski            auto &lastSeq = otherQueueSeqs[wait.queue];
23769867daedbf52debc77d6568162ee21e071699b80Chris Forbes            lastSeq = std::max(lastSeq, wait.seq);
2377da8f07baf262972eb3e719fa07b073c180dff157Chris Forbes        }
2378cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes
2379bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        for (auto &semaphore : submission.signalSemaphores) {
23809a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            auto pSemaphore = GetSemaphoreNode(dev_data, semaphore);
2381c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski            if (pSemaphore) {
2382c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski                pSemaphore->in_use.fetch_sub(1);
2383c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski            }
23849867daedbf52debc77d6568162ee21e071699b80Chris Forbes        }
2385cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes
238606d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt        for (auto &semaphore : submission.externalSemaphores) {
238706d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt            auto pSemaphore = GetSemaphoreNode(dev_data, semaphore);
238806d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt            if (pSemaphore) {
238906d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                pSemaphore->in_use.fetch_sub(1);
239006d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt            }
239106d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt        }
239206d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt
23939867daedbf52debc77d6568162ee21e071699b80Chris Forbes        for (auto cb : submission.cbs) {
23949a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            auto cb_node = GetCBNode(dev_data, cb);
2395c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski            if (!cb_node) {
2396c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski                continue;
2397c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski            }
2398a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis            // First perform decrement on general case bound objects
23999a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis            DecrementBoundResources(dev_data, cb_node);
24009a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis            for (auto drawDataElement : cb_node->drawData) {
24019867daedbf52debc77d6568162ee21e071699b80Chris Forbes                for (auto buffer : drawDataElement.buffers) {
24029a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                    auto buffer_state = GetBufferState(dev_data, buffer);
24035cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis                    if (buffer_state) {
24045cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis                        buffer_state->in_use.fetch_sub(1);
24059867daedbf52debc77d6568162ee21e071699b80Chris Forbes                    }
24069867daedbf52debc77d6568162ee21e071699b80Chris Forbes                }
2407da8f07baf262972eb3e719fa07b073c180dff157Chris Forbes            }
24089a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis            for (auto event : cb_node->writeEventsBeforeWait) {
24099867daedbf52debc77d6568162ee21e071699b80Chris Forbes                auto eventNode = dev_data->eventMap.find(event);
24109867daedbf52debc77d6568162ee21e071699b80Chris Forbes                if (eventNode != dev_data->eventMap.end()) {
24119867daedbf52debc77d6568162ee21e071699b80Chris Forbes                    eventNode->second.write_in_use--;
24129867daedbf52debc77d6568162ee21e071699b80Chris Forbes                }
24139867daedbf52debc77d6568162ee21e071699b80Chris Forbes            }
24149a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis            for (auto queryStatePair : cb_node->queryToStateMap) {
24159867daedbf52debc77d6568162ee21e071699b80Chris Forbes                dev_data->queryToStateMap[queryStatePair.first] = queryStatePair.second;
24169867daedbf52debc77d6568162ee21e071699b80Chris Forbes            }
24179a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis            for (auto eventStagePair : cb_node->eventToStageMap) {
24189867daedbf52debc77d6568162ee21e071699b80Chris Forbes                dev_data->eventMap[eventStagePair.first].stageMask = eventStagePair.second;
2419da8f07baf262972eb3e719fa07b073c180dff157Chris Forbes            }
24200a32ed7bdf03e7bda914e03c0bfa6ebf400cdf5bMichael Lentine
2421a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes            cb_node->in_use.fetch_sub(1);
24220a32ed7bdf03e7bda914e03c0bfa6ebf400cdf5bMichael Lentine        }
24239867daedbf52debc77d6568162ee21e071699b80Chris Forbes
24249a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto pFence = GetFenceNode(dev_data, submission.fence);
2425804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt        if (pFence && pFence->scope == kSyncScopeInternal) {
24269867daedbf52debc77d6568162ee21e071699b80Chris Forbes            pFence->state = FENCE_RETIRED;
24270a32ed7bdf03e7bda914e03c0bfa6ebf400cdf5bMichael Lentine        }
24289867daedbf52debc77d6568162ee21e071699b80Chris Forbes
24299867daedbf52debc77d6568162ee21e071699b80Chris Forbes        pQueue->submissions.pop_front();
24309867daedbf52debc77d6568162ee21e071699b80Chris Forbes        pQueue->seq++;
2431b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine    }
24329867daedbf52debc77d6568162ee21e071699b80Chris Forbes
24339867daedbf52debc77d6568162ee21e071699b80Chris Forbes    // Roll other queues forward to the highest seq we saw a wait for
24349867daedbf52debc77d6568162ee21e071699b80Chris Forbes    for (auto qs : otherQueueSeqs) {
24359a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        RetireWorkOnQueue(dev_data, GetQueueState(dev_data, qs.first), qs.second);
2436d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine    }
24379867daedbf52debc77d6568162ee21e071699b80Chris Forbes}
2438651d92815dfff917308137bb67aacccc4f60df86Chris Forbes
2439651d92815dfff917308137bb67aacccc4f60df86Chris Forbes// Submit a fence to a queue, delimiting previous fences and previous untracked
2440651d92815dfff917308137bb67aacccc4f60df86Chris Forbes// work by it.
244136c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlisstatic void SubmitFence(QUEUE_STATE *pQueue, FENCE_NODE *pFence, uint64_t submitCount) {
2442cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes    pFence->state = FENCE_INFLIGHT;
24439867daedbf52debc77d6568162ee21e071699b80Chris Forbes    pFence->signaler.first = pQueue->queue;
24449867daedbf52debc77d6568162ee21e071699b80Chris Forbes    pFence->signaler.second = pQueue->seq + pQueue->submissions.size() + submitCount;
2445b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine}
2446b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine
244751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourstatic bool validateCommandBufferSimultaneousUse(layer_data *dev_data, GLOBAL_CB_NODE *pCB, int current_submit_count) {
24483251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
2449a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes    if ((pCB->in_use.load() || current_submit_count > 1) &&
24505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        !(pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT)) {
24513251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0,
2452315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        __LINE__, VALIDATION_ERROR_31a0008e, "DS",
24533251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "Command Buffer 0x%p is already in use and is not marked for simultaneous use. %s", pCB->commandBuffer,
2454315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_31a0008e]);
24555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
24563251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
24575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
24585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2459946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinskistatic bool validateCommandBufferState(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, const char *call_source,
24600de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                                       int current_submit_count, UNIQUE_VALIDATION_ERROR_CODE vu_id) {
2461c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis    bool skip = false;
2462cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.command_buffer_state) return skip;
24630a59acde4b40fde3bbfea5811d2abf2c85ca62f4Tobin Ehlis    // Validate ONE_TIME_SUBMIT_BIT CB is not being submitted more than once
2464946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski    if ((cb_state->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT) &&
2465946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski        (cb_state->submitCount + current_submit_count > 1)) {
2466c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0,
2467c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis                        __LINE__, DRAWSTATE_COMMAND_BUFFER_SINGLE_SUBMIT_VIOLATION, "DS",
2468226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis                        "Commandbuffer 0x%p was begun w/ VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT "
2469c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis                        "set, but has been submitted 0x%" PRIxLEAST64 " times.",
2470946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski                        cb_state->commandBuffer, cb_state->submitCount + current_submit_count);
24710a59acde4b40fde3bbfea5811d2abf2c85ca62f4Tobin Ehlis    }
247294307efee520ad91d5da2ff8f40609b31f05b2efChris Forbes
24735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Validate that cmd buffers have been updated
247446daa701a01b92ae19e3ee9e661d677128fe7e6dChris Forbes    switch (cb_state->state) {
247546daa701a01b92ae19e3ee9e661d677128fe7e6dChris Forbes        case CB_INVALID_INCOMPLETE:
247646daa701a01b92ae19e3ee9e661d677128fe7e6dChris Forbes        case CB_INVALID_COMPLETE:
2477946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski            skip |= ReportInvalidCommandBuffer(dev_data, cb_state, call_source);
247846daa701a01b92ae19e3ee9e661d677128fe7e6dChris Forbes            break;
247946daa701a01b92ae19e3ee9e661d677128fe7e6dChris Forbes
248046daa701a01b92ae19e3ee9e661d677128fe7e6dChris Forbes        case CB_NEW:
24810de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
24820de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                            (uint64_t)(cb_state->commandBuffer), __LINE__, vu_id, "DS",
24830de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                            "Command buffer 0x%p used in the call to %s is unrecorded and contains no commands. %s",
24840de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                            cb_state->commandBuffer, call_source, validation_error_map[vu_id]);
248546daa701a01b92ae19e3ee9e661d677128fe7e6dChris Forbes            break;
248646daa701a01b92ae19e3ee9e661d677128fe7e6dChris Forbes
248746daa701a01b92ae19e3ee9e661d677128fe7e6dChris Forbes        case CB_RECORDING:
2488c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
24899b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(cb_state->commandBuffer), __LINE__, DRAWSTATE_NO_END_COMMAND_BUFFER, "DS",
2490946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski                            "You must call vkEndCommandBuffer() on command buffer 0x%p before this call to %s!",
2491946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski                            cb_state->commandBuffer, call_source);
249246daa701a01b92ae19e3ee9e661d677128fe7e6dChris Forbes            break;
249346daa701a01b92ae19e3ee9e661d677128fe7e6dChris Forbes
249446daa701a01b92ae19e3ee9e661d677128fe7e6dChris Forbes        default: /* recorded */
249546daa701a01b92ae19e3ee9e661d677128fe7e6dChris Forbes            break;
24965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
2497c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis    return skip;
24985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
24995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
250051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourstatic bool validateResources(layer_data *dev_data, GLOBAL_CB_NODE *cb_node) {
25013251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
250251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour
250351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    // TODO : We should be able to remove the NULL look-up checks from the code below as long as
250451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    //  all the corresponding cases are verified to cause CB_INVALID state and the CB_INVALID state
250551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    //  should then be flagged prior to calling this function
250651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    for (auto drawDataElement : cb_node->drawData) {
250751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour        for (auto buffer : drawDataElement.buffers) {
250851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour            auto buffer_state = GetBufferState(dev_data, buffer);
250951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour            if (!buffer_state) {
25103251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT,
25119b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                HandleToUint64(buffer), __LINE__, DRAWSTATE_INVALID_BUFFER, "DS",
25129b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                "Cannot submit cmd buffer using deleted buffer 0x%" PRIx64 ".", HandleToUint64(buffer));
251351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour            }
251451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour        }
251551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    }
25163251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
251751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour}
251851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour
2519f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski// Check that the queue family index of 'queue' matches one of the entries in pQueueFamilyIndices
2520f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinskibool ValidImageBufferQueue(layer_data *dev_data, GLOBAL_CB_NODE *cb_node, const VK_OBJECT *object, VkQueue queue, uint32_t count,
2521f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski                           const uint32_t *indices) {
2522f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski    bool found = false;
2523f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski    bool skip = false;
2524f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski    auto queue_state = GetQueueState(dev_data, queue);
2525f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski    if (queue_state) {
2526f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski        for (uint32_t i = 0; i < count; i++) {
2527f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski            if (indices[i] == queue_state->queueFamilyIndex) {
2528f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski                found = true;
2529f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski                break;
2530f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski            }
2531f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski        }
2532f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski
2533f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski        if (!found) {
25349b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus            skip = log_msg(
25359b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, get_debug_report_enum[object->type], object->handle, __LINE__,
25369b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                DRAWSTATE_INVALID_QUEUE_FAMILY, "DS", "vkQueueSubmit: Command buffer 0x%" PRIxLEAST64 " contains %s 0x%" PRIxLEAST64
25379b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                                      " which was not created allowing concurrent access to this queue family %d.",
25389b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                HandleToUint64(cb_node->commandBuffer), object_string[object->type], object->handle, queue_state->queueFamilyIndex);
2539f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski        }
2540f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski    }
2541f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski    return skip;
2542f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski}
2543f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski
25447bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski// Validate that queueFamilyIndices of primary command buffers match this queue
25457bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski// Secondary command buffers were previously validated in vkCmdExecuteCommands().
25467bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinskistatic bool validateQueueFamilyIndices(layer_data *dev_data, GLOBAL_CB_NODE *pCB, VkQueue queue) {
25473251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
25489a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto pPool = GetCommandPoolNode(dev_data, pCB->createInfo.commandPool);
25499a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto queue_state = GetQueueState(dev_data, queue);
25507bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski
2551f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski    if (pPool && queue_state) {
2552f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski        if (pPool->queueFamilyIndex != queue_state->queueFamilyIndex) {
25533251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
2554315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(pCB->commandBuffer), __LINE__, VALIDATION_ERROR_31a00094, "DS",
25553251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "vkQueueSubmit: Primary command buffer 0x%p created in queue family %d is being submitted on queue "
25563251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "0x%p from queue family %d. %s",
25573251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            pCB->commandBuffer, pPool->queueFamilyIndex, queue, queue_state->queueFamilyIndex,
2558315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            validation_error_map[VALIDATION_ERROR_31a00094]);
2559f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski        }
2560f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski
2561f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski        // Ensure that any bound images or buffers created with SHARING_MODE_CONCURRENT have access to the current queue family
2562f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski        for (auto object : pCB->object_bindings) {
25637a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski            if (object.type == kVulkanObjectTypeImage) {
2564f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski                auto image_state = GetImageState(dev_data, reinterpret_cast<VkImage &>(object.handle));
2565f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski                if (image_state && image_state->createInfo.sharingMode == VK_SHARING_MODE_CONCURRENT) {
25663251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= ValidImageBufferQueue(dev_data, pCB, &object, queue, image_state->createInfo.queueFamilyIndexCount,
25673251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                                  image_state->createInfo.pQueueFamilyIndices);
2568f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski                }
25697a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski            } else if (object.type == kVulkanObjectTypeBuffer) {
2570f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski                auto buffer_state = GetBufferState(dev_data, reinterpret_cast<VkBuffer &>(object.handle));
2571f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski                if (buffer_state && buffer_state->createInfo.sharingMode == VK_SHARING_MODE_CONCURRENT) {
25723251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= ValidImageBufferQueue(dev_data, pCB, &object, queue, buffer_state->createInfo.queueFamilyIndexCount,
25733251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                                  buffer_state->createInfo.pQueueFamilyIndices);
2574f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski                }
2575f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski            }
2576f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski        }
25777bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski    }
25787bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski
25793251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
25807bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski}
25817bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski
258251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourstatic bool validatePrimaryCommandBufferState(layer_data *dev_data, GLOBAL_CB_NODE *pCB, int current_submit_count) {
25835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Track in-use for resources off of primary and any secondary CBs
25843251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
2585a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes
2586a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes    // If USAGE_SIMULTANEOUS_USE_BIT not set then CB cannot already be executing
2587a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes    // on device
25883251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    skip |= validateCommandBufferSimultaneousUse(dev_data, pCB, current_submit_count);
2589a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes
25903251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    skip |= validateResources(dev_data, pCB);
2591a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes
25921a3660584634742a3297915c94768d73f360e794Chris Forbes    for (auto pSubCB : pCB->linkedCommandBuffers) {
259311decd82041d4b10aac41360fc76b6fda4f4bd27Chris Forbes        skip |= validateResources(dev_data, pSubCB);
25941a3660584634742a3297915c94768d73f360e794Chris Forbes        // TODO: replace with invalidateCommandBuffers() at recording.
259511decd82041d4b10aac41360fc76b6fda4f4bd27Chris Forbes        if ((pSubCB->primaryCommandBuffer != pCB->commandBuffer) &&
259611decd82041d4b10aac41360fc76b6fda4f4bd27Chris Forbes            !(pSubCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT)) {
2597315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis            log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0,
2598315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                    __LINE__, VALIDATION_ERROR_31a00092, "DS",
2599315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                    "Commandbuffer 0x%p was submitted with secondary buffer 0x%p but that buffer has subsequently been bound to "
2600f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen                    "primary cmd buffer 0x%p and it does not have VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT set. %s",
2601315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                    pCB->commandBuffer, pSubCB->commandBuffer, pSubCB->primaryCommandBuffer,
2602315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                    validation_error_map[VALIDATION_ERROR_31a00092]);
26035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
26045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
2605a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes
2606315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis    skip |= validateCommandBufferState(dev_data, pCB, "vkQueueSubmit()", current_submit_count, VALIDATION_ERROR_31a00090);
2607a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes
26083251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
26095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
26105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2611bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic bool ValidateFenceForSubmit(layer_data *dev_data, FENCE_NODE *pFence) {
26123251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
261381c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes
2614804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt    if (pFence && pFence->scope == kSyncScopeInternal) {
2615cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes        if (pFence->state == FENCE_INFLIGHT) {
2616315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis            // TODO: opportunities for VALIDATION_ERROR_31a00080, VALIDATION_ERROR_316008b4, VALIDATION_ERROR_16400a0e
26173251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT,
26189b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(pFence->fence), __LINE__, DRAWSTATE_INVALID_FENCE, "DS",
26199b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            "Fence 0x%" PRIx64 " is already in use by another submission.", HandleToUint64(pFence->fence));
2620a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis        }
262181c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes
2622cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes        else if (pFence->state == FENCE_RETIRED) {
2623315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis            // TODO: opportunities for VALIDATION_ERROR_31a0007e, VALIDATION_ERROR_316008b2, VALIDATION_ERROR_16400a0e
26243251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT,
26259b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(pFence->fence), __LINE__, MEMTRACK_INVALID_FENCE_STATE, "MEM",
26263251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "Fence 0x%" PRIxLEAST64 " submitted in SIGNALED state.  Fences must be reset before being submitted",
26279b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(pFence->fence));
2628a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis        }
26295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
263081c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes
26313251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
263281c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes}
263381c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes
263451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourstatic void PostCallRecordQueueSubmit(layer_data *dev_data, VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits,
263551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                                      VkFence fence) {
263685926a33d427ee62f395a50886db980127063c72Mike Schuchardt    uint64_t early_retire_seq = 0;
26379a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto pQueue = GetQueueState(dev_data, queue);
26389a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto pFence = GetFenceNode(dev_data, fence);
2639d7d60cccc862fee2d0b3ad410c5fdcc40ddc83aeChris Forbes
26406371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt    if (pFence) {
26416371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt        if (pFence->scope == kSyncScopeInternal) {
26426371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt            // Mark fence in use
26436371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt            SubmitFence(pQueue, pFence, std::max(1u, submitCount));
26446371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt            if (!submitCount) {
26456371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt                // If no submissions, but just dropping a fence on the end of the queue,
26466371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt                // record an empty submission with just the fence, so we can determine
26476371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt                // its completion.
26486371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt                pQueue->submissions.emplace_back(std::vector<VkCommandBuffer>(), std::vector<SEMAPHORE_WAIT>(),
26496371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt                                                 std::vector<VkSemaphore>(), std::vector<VkSemaphore>(), fence);
26506371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt            }
26516371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt        } else {
26526371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt            // Retire work up until this fence early, we will not see the wait that corresponds to this signal
26536371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt            early_retire_seq = pQueue->seq + pQueue->submissions.size();
26546371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt            if (!dev_data->external_sync_warning) {
26556371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt                dev_data->external_sync_warning = true;
26566371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt                log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT,
26576371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt                        HandleToUint64(fence), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS",
26586371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt                        "vkQueueSubmit(): Signaling external fence 0x%" PRIx64 " on queue 0x%" PRIx64
26596371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt                        " will disable validation of preceding command buffer lifecycle states and the in-use status of "
26606371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt                        "associated objects.",
26616371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt                        HandleToUint64(fence), HandleToUint64(queue));
26626371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt            }
26636371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt        }
2664651d92815dfff917308137bb67aacccc4f60df86Chris Forbes    }
2665651d92815dfff917308137bb67aacccc4f60df86Chris Forbes
266651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    // Now process each individual submit
26675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
266851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour        std::vector<VkCommandBuffer> cbs;
26695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        const VkSubmitInfo *submit = &pSubmits[submit_idx];
26709867daedbf52debc77d6568162ee21e071699b80Chris Forbes        vector<SEMAPHORE_WAIT> semaphore_waits;
26719867daedbf52debc77d6568162ee21e071699b80Chris Forbes        vector<VkSemaphore> semaphore_signals;
267206d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt        vector<VkSemaphore> semaphore_externals;
26735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t i = 0; i < submit->waitSemaphoreCount; ++i) {
267451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour            VkSemaphore semaphore = submit->pWaitSemaphores[i];
267551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour            auto pSemaphore = GetSemaphoreNode(dev_data, semaphore);
267651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour            if (pSemaphore) {
267706d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                if (pSemaphore->scope == kSyncScopeInternal) {
267806d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                    if (pSemaphore->signaler.first != VK_NULL_HANDLE) {
267906d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                        semaphore_waits.push_back({semaphore, pSemaphore->signaler.first, pSemaphore->signaler.second});
268006d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                        pSemaphore->in_use.fetch_add(1);
268106d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                    }
268206d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                    pSemaphore->signaler.first = VK_NULL_HANDLE;
268306d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                    pSemaphore->signaled = false;
268406d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                } else {
268506d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                    semaphore_externals.push_back(semaphore);
268651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                    pSemaphore->in_use.fetch_add(1);
268706d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                    if (pSemaphore->scope == kSyncScopeExternalTemporary) {
268806d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                        pSemaphore->scope = kSyncScopeInternal;
268906d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                    }
269051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                }
269151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour            }
269251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour        }
269351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour        for (uint32_t i = 0; i < submit->signalSemaphoreCount; ++i) {
269451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour            VkSemaphore semaphore = submit->pSignalSemaphores[i];
269551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour            auto pSemaphore = GetSemaphoreNode(dev_data, semaphore);
269651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour            if (pSemaphore) {
269706d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                if (pSemaphore->scope == kSyncScopeInternal) {
269806d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                    pSemaphore->signaler.first = queue;
269906d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                    pSemaphore->signaler.second = pQueue->seq + pQueue->submissions.size() + 1;
270006d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                    pSemaphore->signaled = true;
270106d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                    pSemaphore->in_use.fetch_add(1);
270206d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                    semaphore_signals.push_back(semaphore);
270306d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                } else {
270485926a33d427ee62f395a50886db980127063c72Mike Schuchardt                    // Retire work up until this submit early, we will not see the wait that corresponds to this signal
27056371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt                    early_retire_seq = std::max(early_retire_seq, pQueue->seq + pQueue->submissions.size() + 1);
270685926a33d427ee62f395a50886db980127063c72Mike Schuchardt                    if (!dev_data->external_sync_warning) {
270785926a33d427ee62f395a50886db980127063c72Mike Schuchardt                        dev_data->external_sync_warning = true;
270885926a33d427ee62f395a50886db980127063c72Mike Schuchardt                        log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT,
270985926a33d427ee62f395a50886db980127063c72Mike Schuchardt                                HandleToUint64(semaphore), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS",
271085926a33d427ee62f395a50886db980127063c72Mike Schuchardt                                "vkQueueSubmit(): Signaling external semaphore 0x%" PRIx64 " on queue 0x%" PRIx64
271185926a33d427ee62f395a50886db980127063c72Mike Schuchardt                                " will disable validation of preceding command buffer lifecycle states and the in-use status of "
271285926a33d427ee62f395a50886db980127063c72Mike Schuchardt                                "associated objects.",
271385926a33d427ee62f395a50886db980127063c72Mike Schuchardt                                HandleToUint64(semaphore), HandleToUint64(queue));
271485926a33d427ee62f395a50886db980127063c72Mike Schuchardt                    }
271506d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                }
271651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour            }
271751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour        }
271851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour        for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
271951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour            auto cb_node = GetCBNode(dev_data, submit->pCommandBuffers[i]);
272051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour            if (cb_node) {
272151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                cbs.push_back(submit->pCommandBuffers[i]);
27221a3660584634742a3297915c94768d73f360e794Chris Forbes                for (auto secondaryCmdBuffer : cb_node->linkedCommandBuffers) {
272311decd82041d4b10aac41360fc76b6fda4f4bd27Chris Forbes                    cbs.push_back(secondaryCmdBuffer->commandBuffer);
272451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                }
272551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                UpdateCmdBufImageLayouts(dev_data, cb_node);
272651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                incrementResources(dev_data, cb_node);
27271a3660584634742a3297915c94768d73f360e794Chris Forbes                for (auto secondaryCmdBuffer : cb_node->linkedCommandBuffers) {
272811decd82041d4b10aac41360fc76b6fda4f4bd27Chris Forbes                    incrementResources(dev_data, secondaryCmdBuffer);
272951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                }
273051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour            }
273151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour        }
273206d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt        pQueue->submissions.emplace_back(cbs, semaphore_waits, semaphore_signals, semaphore_externals,
273351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                                         submit_idx == submitCount - 1 ? fence : VK_NULL_HANDLE);
273451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    }
273551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour
273685926a33d427ee62f395a50886db980127063c72Mike Schuchardt    if (early_retire_seq) {
273785926a33d427ee62f395a50886db980127063c72Mike Schuchardt        RetireWorkOnQueue(dev_data, pQueue, early_retire_seq);
273885926a33d427ee62f395a50886db980127063c72Mike Schuchardt    }
273951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour}
274051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour
274151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourstatic bool PreCallValidateQueueSubmit(layer_data *dev_data, VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits,
274251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                                       VkFence fence) {
274351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    auto pFence = GetFenceNode(dev_data, fence);
27443251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = ValidateFenceForSubmit(dev_data, pFence);
27453251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (skip) {
274651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour        return true;
274751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    }
274851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour
274951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    unordered_set<VkSemaphore> signaled_semaphores;
275051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    unordered_set<VkSemaphore> unsignaled_semaphores;
275106d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt    unordered_set<VkSemaphore> internal_semaphores;
275251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    vector<VkCommandBuffer> current_cmds;
2753c25ac48846c975d698243e53750c6bca28bba33eChris Forbes    unordered_map<ImageSubresourcePair, IMAGE_LAYOUT_NODE> localImageLayoutMap;
275451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    // Now verify each individual submit
275551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
275651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour        const VkSubmitInfo *submit = &pSubmits[submit_idx];
275751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour        for (uint32_t i = 0; i < submit->waitSemaphoreCount; ++i) {
2758315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis            skip |= ValidateStageMaskGsTsEnables(dev_data, submit->pWaitDstStageMask[i], "vkQueueSubmit()",
2759315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                                 VALIDATION_ERROR_13c00098, VALIDATION_ERROR_13c0009a);
276001a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes            VkSemaphore semaphore = submit->pWaitSemaphores[i];
27619a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            auto pSemaphore = GetSemaphoreNode(dev_data, semaphore);
276206d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt            if (pSemaphore && (pSemaphore->scope == kSyncScopeInternal || internal_semaphores.count(semaphore))) {
276351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                if (unsignaled_semaphores.count(semaphore) ||
2764440bdd357701497c3442e3515f12ac1cfffc180aTony Barbour                    (!(signaled_semaphores.count(semaphore)) && !(pSemaphore->signaled))) {
27653251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT,
27669b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                    HandleToUint64(semaphore), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS",
27673251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    "Queue 0x%p is waiting on semaphore 0x%" PRIx64 " that has no way to be signaled.", queue,
27689b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                    HandleToUint64(semaphore));
276951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                } else {
277051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                    signaled_semaphores.erase(semaphore);
277151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                    unsignaled_semaphores.insert(semaphore);
27721344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis                }
27735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
277406d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt            if (pSemaphore && pSemaphore->scope == kSyncScopeExternalTemporary) {
277506d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                internal_semaphores.insert(semaphore);
277606d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt            }
27775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
27785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t i = 0; i < submit->signalSemaphoreCount; ++i) {
277901a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes            VkSemaphore semaphore = submit->pSignalSemaphores[i];
27809a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            auto pSemaphore = GetSemaphoreNode(dev_data, semaphore);
278106d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt            if (pSemaphore && (pSemaphore->scope == kSyncScopeInternal || internal_semaphores.count(semaphore))) {
2782440bdd357701497c3442e3515f12ac1cfffc180aTony Barbour                if (signaled_semaphores.count(semaphore) || (!(unsignaled_semaphores.count(semaphore)) && pSemaphore->signaled)) {
27833251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT,
27849b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                    HandleToUint64(semaphore), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS",
27853251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    "Queue 0x%p is signaling semaphore 0x%" PRIx64
27863251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    " that has already been signaled but not waited on by queue 0x%" PRIx64 ".",
27879b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                    queue, HandleToUint64(semaphore), HandleToUint64(pSemaphore->signaler.first));
27881344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis                } else {
278951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                    unsignaled_semaphores.erase(semaphore);
279051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                    signaled_semaphores.insert(semaphore);
27911344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis                }
27920a32ed7bdf03e7bda914e03c0bfa6ebf400cdf5bMichael Lentine            }
27935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
27945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
27959a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            auto cb_node = GetCBNode(dev_data, submit->pCommandBuffers[i]);
2796d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis            if (cb_node) {
2797c25ac48846c975d698243e53750c6bca28bba33eChris Forbes                skip |= ValidateCmdBufImageLayouts(dev_data, cb_node, dev_data->imageLayoutMap, localImageLayoutMap);
279851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                current_cmds.push_back(submit->pCommandBuffers[i]);
27993251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= validatePrimaryCommandBufferState(
280051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                    dev_data, cb_node, (int)std::count(current_cmds.begin(), current_cmds.end(), submit->pCommandBuffers[i]));
28013251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= validateQueueFamilyIndices(dev_data, cb_node, queue);
280251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour
2803ea371fa7c8c57edb4d1436e4570cf54f3fc0463fTobin Ehlis                // Potential early exit here as bad object state may crash in delayed function calls
28043251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                if (skip) {
280551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                    return true;
280651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour                }
280751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour
28081344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis                // Call submit-time functions to validate/update state
2809d807198f24437c1b2478ff1d06a33ce4873a1451Tobin Ehlis                for (auto &function : cb_node->queue_submit_functions) {
28103251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= function();
28111344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis                }
2812d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis                for (auto &function : cb_node->eventUpdates) {
28133251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= function(queue);
28141344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis                }
2815d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis                for (auto &function : cb_node->queryUpdates) {
28163251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= function(queue);
2817d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine                }
28181344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis            }
28195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
28209867daedbf52debc77d6568162ee21e071699b80Chris Forbes    }
28213251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
282251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour}
28239867daedbf52debc77d6568162ee21e071699b80Chris Forbes
282451920949f887ce8d3666c73c28ff19a5d8325a37Tony BarbourVKAPI_ATTR VkResult VKAPI_CALL QueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence) {
282551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map);
2826ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
282751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour
282851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    bool skip = PreCallValidateQueueSubmit(dev_data, queue, submitCount, pSubmits, fence);
2829b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
28305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2831440bdd357701497c3442e3515f12ac1cfffc180aTony Barbour    if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
283251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour
283351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    VkResult result = dev_data->dispatch_table.QueueSubmit(queue, submitCount, pSubmits, fence);
283451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour
283551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    lock.lock();
283651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    PostCallRecordQueueSubmit(dev_data, queue, submitCount, pSubmits, fence);
283751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour    lock.unlock();
28385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
28395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
28405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2841f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultzstatic bool PreCallValidateAllocateMemory(layer_data *dev_data) {
2842f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz    bool skip = false;
2843f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz    if (dev_data->memObjMap.size() >= dev_data->phys_dev_properties.properties.limits.maxMemoryAllocationCount) {
2844f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
2845315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(dev_data->device), __LINE__, VALIDATION_ERROR_16c004f8, "MEM",
2846f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz                        "Number of currently valid memory objects is not less than the maximum allowed (%u). %s",
2847f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz                        dev_data->phys_dev_properties.properties.limits.maxMemoryAllocationCount,
2848315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_16c004f8]);
2849f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz    }
2850f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz    return skip;
2851f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz}
2852f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz
2853f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultzstatic void PostCallRecordAllocateMemory(layer_data *dev_data, const VkMemoryAllocateInfo *pAllocateInfo, VkDeviceMemory *pMemory) {
2854f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz    add_mem_obj_info(dev_data, dev_data->device, *pMemory, pAllocateInfo);
2855f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz    return;
2856f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz}
2857f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz
285889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL AllocateMemory(VkDevice device, const VkMemoryAllocateInfo *pAllocateInfo,
285989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                              const VkAllocationCallbacks *pAllocator, VkDeviceMemory *pMemory) {
2860f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
286156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
2862ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
2863f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz    bool skip = PreCallValidateAllocateMemory(dev_data);
2864f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz    if (!skip) {
2865f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz        lock.unlock();
2866f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz        result = dev_data->dispatch_table.AllocateMemory(device, pAllocateInfo, pAllocator, pMemory);
2867f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz        lock.lock();
2868f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz        if (VK_SUCCESS == result) {
2869f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz            PostCallRecordAllocateMemory(dev_data, pAllocateInfo, pMemory);
2870f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz        }
2871e12739a56d02ca2fb5f0273862668e7475a21a6cMark Lobodzinski    }
28725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
28735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
28745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2875177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis// For given obj node, if it is use, flag a validation error and return callback result, else return false
287669ea2c79d7b3f9c987671a10686afac066b275b9Mike Schuchardtbool ValidateObjectNotInUse(const layer_data *dev_data, BASE_NODE *obj_node, VK_OBJECT obj_struct, const char *caller_name,
2877177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis                            UNIQUE_VALIDATION_ERROR_CODE error_code) {
2878cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.object_in_use) return false;
2879177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis    bool skip = false;
2880177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis    if (obj_node->in_use.load()) {
288169ea2c79d7b3f9c987671a10686afac066b275b9Mike Schuchardt        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, get_debug_report_enum[obj_struct.type],
288269ea2c79d7b3f9c987671a10686afac066b275b9Mike Schuchardt                        obj_struct.handle, __LINE__, error_code, "DS",
288369ea2c79d7b3f9c987671a10686afac066b275b9Mike Schuchardt                        "Cannot call %s on %s 0x%" PRIx64 " that is currently in use by a command buffer. %s", caller_name,
288469ea2c79d7b3f9c987671a10686afac066b275b9Mike Schuchardt                        object_string[obj_struct.type], obj_struct.handle, validation_error_map[error_code]);
2885177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis    }
2886177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis    return skip;
2887177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis}
28885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2889177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlisstatic bool PreCallValidateFreeMemory(layer_data *dev_data, VkDeviceMemory mem, DEVICE_MEM_INFO **mem_info, VK_OBJECT *obj_struct) {
28909a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    *mem_info = GetMemObjInfo(dev_data, mem);
28919b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus    *obj_struct = {HandleToUint64(mem), kVulkanObjectTypeDeviceMemory};
2892cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.free_memory) return false;
2893177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis    bool skip = false;
2894177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis    if (*mem_info) {
289569ea2c79d7b3f9c987671a10686afac066b275b9Mike Schuchardt        skip |= ValidateObjectNotInUse(dev_data, *mem_info, *obj_struct, "vkFreeMemory", VALIDATION_ERROR_2880054a);
2896177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis    }
2897177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis    return skip;
2898177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis}
28995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2900177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlisstatic void PostCallRecordFreeMemory(layer_data *dev_data, VkDeviceMemory mem, DEVICE_MEM_INFO *mem_info, VK_OBJECT obj_struct) {
2901177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis    // Clear mem binding for any bound objects
290247705d01140c9f1492885e6efc5fa262e7e1c6a0Tobin Ehlis    for (auto obj : mem_info->obj_bindings) {
290302a510945ff39f3d9e486e456aca5bfa6ea0c43aMark Lobodzinski        log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, get_debug_report_enum[obj.type], obj.handle, __LINE__,
29047a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski                MEMTRACK_FREED_MEM_REF, "MEM", "VK Object 0x%" PRIxLEAST64 " still has a reference to mem obj 0x%" PRIxLEAST64,
29059b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                obj.handle, HandleToUint64(mem_info->mem));
290647705d01140c9f1492885e6efc5fa262e7e1c6a0Tobin Ehlis        switch (obj.type) {
29077a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski            case kVulkanObjectTypeImage: {
29089a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                auto image_state = GetImageState(dev_data, reinterpret_cast<VkImage &>(obj.handle));
2909cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                assert(image_state);  // Any destroyed images should already be removed from bindings
2910cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                image_state->binding.mem = MEMORY_UNBOUND;
2911cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                break;
2912cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            }
29137a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski            case kVulkanObjectTypeBuffer: {
29149a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                auto buffer_state = GetBufferState(dev_data, reinterpret_cast<VkBuffer &>(obj.handle));
2915cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                assert(buffer_state);  // Any destroyed buffers should already be removed from bindings
2916cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                buffer_state->binding.mem = MEMORY_UNBOUND;
2917cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                break;
2918cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            }
2919cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            default:
2920cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                // Should only have buffer or image objects bound to memory
2921cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                assert(0);
2922177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis        }
2923177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis    }
2924177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis    // Any bound cmd buffers are now invalid
292539c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis    invalidateCommandBuffers(dev_data, mem_info->cb_bindings, obj_struct);
2926177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis    dev_data->memObjMap.erase(mem);
2927177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis}
2928177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis
2929177063aac84fac6f4e650c2629a08b48be643f96Tobin EhlisVKAPI_ATTR void VKAPI_CALL FreeMemory(VkDevice device, VkDeviceMemory mem, const VkAllocationCallbacks *pAllocator) {
293056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
2931177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis    DEVICE_MEM_INFO *mem_info = nullptr;
2932177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis    VK_OBJECT obj_struct;
2933ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
2934177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis    bool skip = PreCallValidateFreeMemory(dev_data, mem, &mem_info, &obj_struct);
2935177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis    if (!skip) {
2936177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis        lock.unlock();
2937177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis        dev_data->dispatch_table.FreeMemory(device, mem, pAllocator);
2938177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis        lock.lock();
2939405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        if (mem != VK_NULL_HANDLE) {
2940405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour            PostCallRecordFreeMemory(dev_data, mem, mem_info, obj_struct);
2941405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        }
294274243a735fe102b370237ddf80d3e6f7ec5246dbMark Mueller    }
29435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
29445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
2945f57fc64ac43691ad98e1713886b345465573070aTobin Ehlis// Validate that given Map memory range is valid. This means that the memory should not already be mapped,
2946f57fc64ac43691ad98e1713886b345465573070aTobin Ehlis//  and that the size of the map range should be:
2947f57fc64ac43691ad98e1713886b345465573070aTobin Ehlis//  1. Not zero
2948f57fc64ac43691ad98e1713886b345465573070aTobin Ehlis//  2. Within the size of the memory allocation
294951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool ValidateMapMemRange(layer_data *dev_data, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size) {
29503251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
29515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
29525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (size == 0) {
29533251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
29549b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                       HandleToUint64(mem), __LINE__, MEMTRACK_INVALID_MAP, "MEM",
29553251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                       "VkMapMemory: Attempting to map memory range of size zero");
29565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
29575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
295851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    auto mem_element = dev_data->memObjMap.find(mem);
295951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    if (mem_element != dev_data->memObjMap.end()) {
296057fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis        auto mem_info = mem_element->second.get();
29615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // It is an application error to call VkMapMemory on an object that is already mapped
2962de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis        if (mem_info->mem_range.size != 0) {
29639b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus            skip =
29649b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
29659b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        HandleToUint64(mem), __LINE__, MEMTRACK_INVALID_MAP, "MEM",
29669b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        "VkMapMemory: Attempting to map memory on an already-mapped object 0x%" PRIxLEAST64, HandleToUint64(mem));
29675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
29685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
29695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // Validate that offset + size is within object's allocationSize
29705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (size == VK_WHOLE_SIZE) {
2971de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis            if (offset >= mem_info->alloc_info.allocationSize) {
29723251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
29739b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                               HandleToUint64(mem), __LINE__, MEMTRACK_INVALID_MAP, "MEM",
29743251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                               "Mapping Memory from 0x%" PRIx64 " to 0x%" PRIx64
29753251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                               " with size of VK_WHOLE_SIZE oversteps total array size 0x%" PRIx64,
29763251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                               offset, mem_info->alloc_info.allocationSize, mem_info->alloc_info.allocationSize);
29775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
29785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else {
2979de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis            if ((offset + size) > mem_info->alloc_info.allocationSize) {
29803251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
2981315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                               HandleToUint64(mem), __LINE__, VALIDATION_ERROR_31200552, "MEM",
29823251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                               "Mapping Memory from 0x%" PRIx64 " to 0x%" PRIx64 " oversteps total array size 0x%" PRIx64 ". %s",
29833251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                               offset, size + offset, mem_info->alloc_info.allocationSize,
2984315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                               validation_error_map[VALIDATION_ERROR_31200552]);
29855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
29865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
29875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
29883251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
29895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
29905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
299151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic void storeMemRanges(layer_data *dev_data, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size) {
29929a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto mem_info = GetMemObjInfo(dev_data, mem);
299357fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis    if (mem_info) {
2994de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis        mem_info->mem_range.offset = offset;
2995de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis        mem_info->mem_range.size = size;
29965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
29975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
29985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
299951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool deleteMemRanges(layer_data *dev_data, VkDeviceMemory mem) {
30003251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
30019a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto mem_info = GetMemObjInfo(dev_data, mem);
300257fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis    if (mem_info) {
3003de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis        if (!mem_info->mem_range.size) {
30045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            // Valid Usage: memory must currently be mapped
30053251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
3006315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                           HandleToUint64(mem), __LINE__, VALIDATION_ERROR_33600562, "MEM",
30079b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                           "Unmapping Memory without memory being mapped: mem obj 0x%" PRIxLEAST64 ". %s", HandleToUint64(mem),
3008315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                           validation_error_map[VALIDATION_ERROR_33600562]);
30095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
3010de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis        mem_info->mem_range.size = 0;
30115f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski        if (mem_info->shadow_copy) {
30125f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            free(mem_info->shadow_copy_base);
30135f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            mem_info->shadow_copy_base = 0;
30145f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            mem_info->shadow_copy = 0;
30155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
30165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
30173251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
30185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
30195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
30205f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski// Guard value for pad data
30215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic char NoncoherentMemoryFillValue = 0xb;
30225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
30235f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinskistatic void initializeAndTrackMemory(layer_data *dev_data, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size,
30245f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski                                     void **ppData) {
30259a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto mem_info = GetMemObjInfo(dev_data, mem);
302657fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis    if (mem_info) {
3027de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis        mem_info->p_driver_data = *ppData;
3028de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis        uint32_t index = mem_info->alloc_info.memoryTypeIndex;
3029b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis        if (dev_data->phys_dev_mem_props.memoryTypes[index].propertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) {
30305f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            mem_info->shadow_copy = 0;
30315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else {
30325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (size == VK_WHOLE_SIZE) {
30335f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski                size = mem_info->alloc_info.allocationSize - offset;
30345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
30355f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            mem_info->shadow_pad_size = dev_data->phys_dev_properties.properties.limits.minMemoryMapAlignment;
303616769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton            assert(SafeModulo(mem_info->shadow_pad_size,
30375f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski                                  dev_data->phys_dev_properties.properties.limits.minMemoryMapAlignment) == 0);
30385f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            // Ensure start of mapped region reflects hardware alignment constraints
30395f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            uint64_t map_alignment = dev_data->phys_dev_properties.properties.limits.minMemoryMapAlignment;
30405f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski
30415f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            // From spec: (ppData - offset) must be aligned to at least limits::minMemoryMapAlignment.
30425f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            uint64_t start_offset = offset % map_alignment;
30435f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            // Data passed to driver will be wrapped by a guardband of data to detect over- or under-writes.
3044bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski            mem_info->shadow_copy_base =
3045bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                malloc(static_cast<size_t>(2 * mem_info->shadow_pad_size + size + map_alignment + start_offset));
30465f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski
30475f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            mem_info->shadow_copy =
30485f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski                reinterpret_cast<char *>((reinterpret_cast<uintptr_t>(mem_info->shadow_copy_base) + map_alignment) &
3049bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                         ~(map_alignment - 1)) +
3050bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                start_offset;
305116769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton            assert(SafeModulo(reinterpret_cast<uintptr_t>(mem_info->shadow_copy) + mem_info->shadow_pad_size - start_offset,
30525f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski                                  map_alignment) == 0);
30535f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski
30546e17c244b21ce43ac57404a00a0d844039eed363Mark Lobodzinski            memset(mem_info->shadow_copy, NoncoherentMemoryFillValue, static_cast<size_t>(2 * mem_info->shadow_pad_size + size));
30555f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            *ppData = static_cast<char *>(mem_info->shadow_copy) + mem_info->shadow_pad_size;
30565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
30575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
30585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
30595f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski
3060a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis// Verify that state for fence being waited on is appropriate. That is,
30619867daedbf52debc77d6568162ee21e071699b80Chris Forbes//  a fence being waited on should not already be signaled and
3062a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis//  it should have been submitted on a queue or during acquire next image
306349f6132af865afd5b7f413c91125971ac97c135aChris Forbesstatic inline bool verifyWaitFenceState(layer_data *dev_data, VkFence fence, const char *apiCall) {
30643251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
30659b48b44dd917f95b5f34dd629ec4076fc87eb3a2Chris Forbes
30669a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto pFence = GetFenceNode(dev_data, fence);
3067804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt    if (pFence && pFence->scope == kSyncScopeInternal) {
3068cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes        if (pFence->state == FENCE_UNSIGNALED) {
30693251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT,
30709b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(fence), __LINE__, MEMTRACK_INVALID_FENCE_STATE, "MEM",
30713251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "%s called for fence 0x%" PRIxLEAST64
30723251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            " which has not been submitted on a Queue or during "
30733251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "acquire next image.",
30749b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            apiCall, HandleToUint64(fence));
30755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
30765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
30773251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
30785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
3079a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis
3080b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlisstatic void RetireFence(layer_data *dev_data, VkFence fence) {
30819a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto pFence = GetFenceNode(dev_data, fence);
3082804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt    if (pFence->scope == kSyncScopeInternal) {
3083804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt        if (pFence->signaler.first != VK_NULL_HANDLE) {
3084804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt            // Fence signaller is a queue -- use this as proof that prior operations on that queue have completed.
3085804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt            RetireWorkOnQueue(dev_data, GetQueueState(dev_data, pFence->signaler.first), pFence->signaler.second);
3086804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt        } else {
3087804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt            // Fence signaller is the WSI. We're not tracking what the WSI op actually /was/ in CV yet, but we need to mark
3088804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt            // the fence as retired.
3089804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt            pFence->state = FENCE_RETIRED;
3090804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt        }
3091d4513979120463171eb479cdded9336eb9944da1Chris Forbes    }
3092b3ecd4c1fb44a2e65dfc13256afa9150aabde1d4Chris Forbes}
3093b3ecd4c1fb44a2e65dfc13256afa9150aabde1d4Chris Forbes
3094accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlisstatic bool PreCallValidateWaitForFences(layer_data *dev_data, uint32_t fence_count, const VkFence *fences) {
3095cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.wait_for_fences) return false;
3096accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis    bool skip = false;
3097accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis    for (uint32_t i = 0; i < fence_count; i++) {
3098accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis        skip |= verifyWaitFenceState(dev_data, fences[i], "vkWaitForFences");
3099b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis        skip |= VerifyQueueStateToFence(dev_data, fences[i]);
3100accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis    }
3101accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis    return skip;
3102accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis}
3103accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis
3104b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlisstatic void PostCallRecordWaitForFences(layer_data *dev_data, uint32_t fence_count, const VkFence *fences, VkBool32 wait_all) {
3105b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis    // When we know that all fences are complete we can clean/remove their CBs
3106accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis    if ((VK_TRUE == wait_all) || (1 == fence_count)) {
3107accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis        for (uint32_t i = 0; i < fence_count; i++) {
3108b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis            RetireFence(dev_data, fences[i]);
3109accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis        }
3110accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis    }
3111accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis    // NOTE : Alternate case not handled here is when some fences have completed. In
3112accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis    //  this case for app to guarantee which fences completed it will have to call
3113b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis    //  vkGetFenceStatus() at which point we'll clean/remove their CBs if complete.
3114accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis}
3115accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis
3116bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL WaitForFences(VkDevice device, uint32_t fenceCount, const VkFence *pFences, VkBool32 waitAll,
3117bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                             uint64_t timeout) {
311856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
31195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Verify fence status of submitted fences
3120ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
3121accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis    bool skip = PreCallValidateWaitForFences(dev_data, fenceCount, pFences);
3122b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
3123cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
3124a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis
31254a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.WaitForFences(device, fenceCount, pFences, waitAll, timeout);
3126414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller
31275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (result == VK_SUCCESS) {
3128b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.lock();
3129b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis        PostCallRecordWaitForFences(dev_data, fenceCount, pFences, waitAll);
3130b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.unlock();
31315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
31325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
31335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
31345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
3135f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlisstatic bool PreCallValidateGetFenceStatus(layer_data *dev_data, VkFence fence) {
3136cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.get_fence_state) return false;
3137f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis    return verifyWaitFenceState(dev_data, fence, "vkGetFenceStatus");
3138f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis}
3139f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis
3140b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlisstatic void PostCallRecordGetFenceStatus(layer_data *dev_data, VkFence fence) { RetireFence(dev_data, fence); }
3141f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis
314289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL GetFenceStatus(VkDevice device, VkFence fence) {
314356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
3144ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
3145f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis    bool skip = PreCallValidateGetFenceStatus(dev_data, fence);
3146b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
3147cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
3148a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis
31494a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.GetFenceStatus(device, fence);
31505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (result == VK_SUCCESS) {
3151f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis        lock.lock();
3152b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis        PostCallRecordGetFenceStatus(dev_data, fence);
3153f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis        lock.unlock();
31545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
31555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
31565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
31575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
31583b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlisstatic void PostCallRecordGetDeviceQueue(layer_data *dev_data, uint32_t q_family_index, VkQueue queue) {
31593b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis    // Add queue to tracking set only if it is new
31603b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis    auto result = dev_data->queues.emplace(queue);
31613b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis    if (result.second == true) {
316236c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlis        QUEUE_STATE *queue_state = &dev_data->queueMap[queue];
31633b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis        queue_state->queue = queue;
31643b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis        queue_state->queueFamilyIndex = q_family_index;
31653b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis        queue_state->seq = 0;
31663b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis    }
31673b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis}
31683b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis
3169bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL GetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue *pQueue) {
317056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
31714a0754042cf090e131e9e769d8a3633c228625beChris Forbes    dev_data->dispatch_table.GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);
3172ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    lock_guard_t lock(global_lock);
3173b376edacad6f7ab3fcc0a914e9b1673a9fcd5143Mark Lobodzinski
31743b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis    PostCallRecordGetDeviceQueue(dev_data, queueFamilyIndex, *pQueue);
31755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
31765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
317736c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlisstatic bool PreCallValidateQueueWaitIdle(layer_data *dev_data, VkQueue queue, QUEUE_STATE **queue_state) {
31789a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    *queue_state = GetQueueState(dev_data, queue);
3179cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.queue_wait_idle) return false;
3180e0cec9ec6dd3cfd83345cabba55ec021681801dbTobin Ehlis    return VerifyQueueStateToSeq(dev_data, *queue_state, (*queue_state)->seq + (*queue_state)->submissions.size());
31814273a1c157585a645dca4c960086032793899d05Tobin Ehlis}
31824273a1c157585a645dca4c960086032793899d05Tobin Ehlis
318336c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlisstatic void PostCallRecordQueueWaitIdle(layer_data *dev_data, QUEUE_STATE *queue_state) {
3184e0cec9ec6dd3cfd83345cabba55ec021681801dbTobin Ehlis    RetireWorkOnQueue(dev_data, queue_state, queue_state->seq + queue_state->submissions.size());
31854273a1c157585a645dca4c960086032793899d05Tobin Ehlis}
31864273a1c157585a645dca4c960086032793899d05Tobin Ehlis
318789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL QueueWaitIdle(VkQueue queue) {
318856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map);
318936c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlis    QUEUE_STATE *queue_state = nullptr;
3190ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
31914273a1c157585a645dca4c960086032793899d05Tobin Ehlis    bool skip = PreCallValidateQueueWaitIdle(dev_data, queue, &queue_state);
31929867daedbf52debc77d6568162ee21e071699b80Chris Forbes    lock.unlock();
3193cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
31944a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.QueueWaitIdle(queue);
31954273a1c157585a645dca4c960086032793899d05Tobin Ehlis    if (VK_SUCCESS == result) {
3196e0cec9ec6dd3cfd83345cabba55ec021681801dbTobin Ehlis        lock.lock();
3197e0cec9ec6dd3cfd83345cabba55ec021681801dbTobin Ehlis        PostCallRecordQueueWaitIdle(dev_data, queue_state);
3198e0cec9ec6dd3cfd83345cabba55ec021681801dbTobin Ehlis        lock.unlock();
31994273a1c157585a645dca4c960086032793899d05Tobin Ehlis    }
32005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
32015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
32025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
32038767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlisstatic bool PreCallValidateDeviceWaitIdle(layer_data *dev_data) {
3204cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.device_wait_idle) return false;
32058767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis    bool skip = false;
32068767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis    for (auto &queue : dev_data->queueMap) {
32078767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis        skip |= VerifyQueueStateToSeq(dev_data, &queue.second, queue.second.seq + queue.second.submissions.size());
32088767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis    }
32098767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis    return skip;
32108767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis}
32118767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis
32128767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlisstatic void PostCallRecordDeviceWaitIdle(layer_data *dev_data) {
32138767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis    for (auto &queue : dev_data->queueMap) {
32148767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis        RetireWorkOnQueue(dev_data, &queue.second, queue.second.seq + queue.second.submissions.size());
32158767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis    }
32168767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis}
32178767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis
321889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL DeviceWaitIdle(VkDevice device) {
321956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
3220ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
32218767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis    bool skip = PreCallValidateDeviceWaitIdle(dev_data);
3222b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
3223cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
32244a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.DeviceWaitIdle(device);
32258767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis    if (VK_SUCCESS == result) {
32268767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis        lock.lock();
32278767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis        PostCallRecordDeviceWaitIdle(dev_data);
32288767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis        lock.unlock();
32298767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis    }
32305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
32315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
32325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
32331d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlisstatic bool PreCallValidateDestroyFence(layer_data *dev_data, VkFence fence, FENCE_NODE **fence_node, VK_OBJECT *obj_struct) {
32349a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    *fence_node = GetFenceNode(dev_data, fence);
32359b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus    *obj_struct = {HandleToUint64(fence), kVulkanObjectTypeFence};
3236cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.destroy_fence) return false;
32371d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis    bool skip = false;
32381d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis    if (*fence_node) {
3239804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt        if ((*fence_node)->scope == kSyncScopeInternal && (*fence_node)->state == FENCE_INFLIGHT) {
32401d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT,
3241315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(fence), __LINE__, VALIDATION_ERROR_24e008c0, "DS", "Fence 0x%" PRIx64 " is in use. %s",
3242315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(fence), validation_error_map[VALIDATION_ERROR_24e008c0]);
32431d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis        }
32441d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis    }
32451d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis    return skip;
32461d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis}
32471d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis
32481d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlisstatic void PostCallRecordDestroyFence(layer_data *dev_data, VkFence fence) { dev_data->fenceMap.erase(fence); }
32491d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis
325089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL DestroyFence(VkDevice device, VkFence fence, const VkAllocationCallbacks *pAllocator) {
325156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
32521d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis    // Common data objects used pre & post call
32531d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis    FENCE_NODE *fence_node = nullptr;
32541d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis    VK_OBJECT obj_struct;
3255ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
32561d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis    bool skip = PreCallValidateDestroyFence(dev_data, fence, &fence_node, &obj_struct);
32571344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis
32581d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis    if (!skip) {
32591d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis        lock.unlock();
32604a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.DestroyFence(device, fence, pAllocator);
32611d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis        lock.lock();
32621d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis        PostCallRecordDestroyFence(dev_data, fence);
32631d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis    }
32645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
32655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
3266c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlisstatic bool PreCallValidateDestroySemaphore(layer_data *dev_data, VkSemaphore semaphore, SEMAPHORE_NODE **sema_node,
3267c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis                                            VK_OBJECT *obj_struct) {
32689a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    *sema_node = GetSemaphoreNode(dev_data, semaphore);
32699b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus    *obj_struct = {HandleToUint64(semaphore), kVulkanObjectTypeSemaphore};
3270cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.destroy_semaphore) return false;
3271c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis    bool skip = false;
3272c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis    if (*sema_node) {
327369ea2c79d7b3f9c987671a10686afac066b275b9Mike Schuchardt        skip |= ValidateObjectNotInUse(dev_data, *sema_node, *obj_struct, "vkDestroySemaphore", VALIDATION_ERROR_268008e2);
3274c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis    }
3275c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis    return skip;
3276c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis}
3277c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis
3278c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlisstatic void PostCallRecordDestroySemaphore(layer_data *dev_data, VkSemaphore sema) { dev_data->semaphoreMap.erase(sema); }
3279c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis
3280bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroySemaphore(VkDevice device, VkSemaphore semaphore, const VkAllocationCallbacks *pAllocator) {
328156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
3282c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis    SEMAPHORE_NODE *sema_node;
3283c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis    VK_OBJECT obj_struct;
3284ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
3285c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis    bool skip = PreCallValidateDestroySemaphore(dev_data, semaphore, &sema_node, &obj_struct);
3286eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis    if (!skip) {
3287eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis        lock.unlock();
32884a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.DestroySemaphore(device, semaphore, pAllocator);
3289c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis        lock.lock();
3290c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis        PostCallRecordDestroySemaphore(dev_data, semaphore);
329199d938c90c2f000ee73fb13513dacf84ffa5651fMark Mueller    }
32925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
32935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
32944710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlisstatic bool PreCallValidateDestroyEvent(layer_data *dev_data, VkEvent event, EVENT_STATE **event_state, VK_OBJECT *obj_struct) {
32959a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    *event_state = GetEventNode(dev_data, event);
32969b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus    *obj_struct = {HandleToUint64(event), kVulkanObjectTypeEvent};
3297cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.destroy_event) return false;
3298d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis    bool skip = false;
3299d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis    if (*event_state) {
330069ea2c79d7b3f9c987671a10686afac066b275b9Mike Schuchardt        skip |= ValidateObjectNotInUse(dev_data, *event_state, *obj_struct, "vkDestroyEvent", VALIDATION_ERROR_24c008f2);
3301d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis    }
3302d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis    return skip;
3303d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis}
3304d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis
33054710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlisstatic void PostCallRecordDestroyEvent(layer_data *dev_data, VkEvent event, EVENT_STATE *event_state, VK_OBJECT obj_struct) {
330639c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis    invalidateCommandBuffers(dev_data, event_state->cb_bindings, obj_struct);
3307d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis    dev_data->eventMap.erase(event);
3308d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis}
3309d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis
331089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL DestroyEvent(VkDevice device, VkEvent event, const VkAllocationCallbacks *pAllocator) {
331156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
33124710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis    EVENT_STATE *event_state = nullptr;
3313d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis    VK_OBJECT obj_struct;
3314ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
3315d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis    bool skip = PreCallValidateDestroyEvent(dev_data, event, &event_state, &obj_struct);
3316f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis    if (!skip) {
3317f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis        lock.unlock();
33184a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.DestroyEvent(device, event, pAllocator);
3319d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis        lock.lock();
3320405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        if (event != VK_NULL_HANDLE) {
3321405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour            PostCallRecordDestroyEvent(dev_data, event, event_state, obj_struct);
3322405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        }
3323f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis    }
33245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
33255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
332683c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlisstatic bool PreCallValidateDestroyQueryPool(layer_data *dev_data, VkQueryPool query_pool, QUERY_POOL_NODE **qp_state,
332783c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis                                            VK_OBJECT *obj_struct) {
33289a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    *qp_state = GetQueryPoolNode(dev_data, query_pool);
33299b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus    *obj_struct = {HandleToUint64(query_pool), kVulkanObjectTypeQueryPool};
3330cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.destroy_query_pool) return false;
333183c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis    bool skip = false;
333283c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis    if (*qp_state) {
333369ea2c79d7b3f9c987671a10686afac066b275b9Mike Schuchardt        skip |= ValidateObjectNotInUse(dev_data, *qp_state, *obj_struct, "vkDestroyQueryPool", VALIDATION_ERROR_26200632);
333483c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis    }
333583c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis    return skip;
333683c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis}
333783c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis
3338bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic void PostCallRecordDestroyQueryPool(layer_data *dev_data, VkQueryPool query_pool, QUERY_POOL_NODE *qp_state,
3339bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                           VK_OBJECT obj_struct) {
334083c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis    invalidateCommandBuffers(dev_data, qp_state->cb_bindings, obj_struct);
334183c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis    dev_data->queryPoolMap.erase(query_pool);
334283c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis}
334383c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis
3344bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyQueryPool(VkDevice device, VkQueryPool queryPool, const VkAllocationCallbacks *pAllocator) {
334556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
334683c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis    QUERY_POOL_NODE *qp_state = nullptr;
334783c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis    VK_OBJECT obj_struct;
3348ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
334983c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis    bool skip = PreCallValidateDestroyQueryPool(dev_data, queryPool, &qp_state, &obj_struct);
3350f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis    if (!skip) {
3351f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis        lock.unlock();
33524a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.DestroyQueryPool(device, queryPool, pAllocator);
335383c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis        lock.lock();
3354405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        if (queryPool != VK_NULL_HANDLE) {
3355405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour            PostCallRecordDestroyQueryPool(dev_data, queryPool, qp_state, obj_struct);
3356405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        }
3357f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis    }
33585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
33599fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlisstatic bool PreCallValidateGetQueryPoolResults(layer_data *dev_data, VkQueryPool query_pool, uint32_t first_query,
33609fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                                               uint32_t query_count, VkQueryResultFlags flags,
33619fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                                               unordered_map<QueryObject, vector<VkCommandBuffer>> *queries_in_flight) {
3362b36fb5ae8886f797de57fa6e14e8ccb079edef8eMark Lobodzinski    bool skip = false;
3363b36fb5ae8886f797de57fa6e14e8ccb079edef8eMark Lobodzinski    auto query_pool_state = dev_data->queryPoolMap.find(query_pool);
3364b36fb5ae8886f797de57fa6e14e8ccb079edef8eMark Lobodzinski    if (query_pool_state != dev_data->queryPoolMap.end()) {
3365b36fb5ae8886f797de57fa6e14e8ccb079edef8eMark Lobodzinski        if ((query_pool_state->second.createInfo.queryType == VK_QUERY_TYPE_TIMESTAMP) && (flags & VK_QUERY_RESULT_PARTIAL_BIT)) {
3366b36fb5ae8886f797de57fa6e14e8ccb079edef8eMark Lobodzinski            skip |= log_msg(
3367b36fb5ae8886f797de57fa6e14e8ccb079edef8eMark Lobodzinski                dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, __LINE__,
3368b36fb5ae8886f797de57fa6e14e8ccb079edef8eMark Lobodzinski                VALIDATION_ERROR_2fa00664, "DS",
3369b36fb5ae8886f797de57fa6e14e8ccb079edef8eMark Lobodzinski                "QueryPool 0x%" PRIx64
3370b36fb5ae8886f797de57fa6e14e8ccb079edef8eMark Lobodzinski                " was created with a queryType of VK_QUERY_TYPE_TIMESTAMP but flags contains VK_QUERY_RESULT_PARTIAL_BIT. %s",
3371b36fb5ae8886f797de57fa6e14e8ccb079edef8eMark Lobodzinski                HandleToUint64(query_pool), validation_error_map[VALIDATION_ERROR_2fa00664]);
3372b36fb5ae8886f797de57fa6e14e8ccb079edef8eMark Lobodzinski        }
3373b36fb5ae8886f797de57fa6e14e8ccb079edef8eMark Lobodzinski    }
3374b36fb5ae8886f797de57fa6e14e8ccb079edef8eMark Lobodzinski
3375a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes    // TODO: clean this up, it's insanely wasteful.
3376a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes    for (auto cmd_buffer : dev_data->commandBufferMap) {
3377a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes        if (cmd_buffer.second->in_use.load()) {
3378a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes            for (auto query_state_pair : cmd_buffer.second->queryToStateMap) {
3379b022d1937f5e9d9f87eef1097b4bf6f3b4043c9dMark Lobodzinski                (*queries_in_flight)[query_state_pair.first].push_back(cmd_buffer.first);
3380a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes            }
33815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
33825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
3383b022d1937f5e9d9f87eef1097b4bf6f3b4043c9dMark Lobodzinski
3384cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.get_query_pool_results) return false;
33859fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis    for (uint32_t i = 0; i < query_count; ++i) {
33869fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis        QueryObject query = {query_pool, first_query + i};
33879fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis        auto qif_pair = queries_in_flight->find(query);
33889fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis        auto query_state_pair = dev_data->queryToStateMap.find(query);
33899fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis        if (query_state_pair != dev_data->queryToStateMap.end()) {
3390ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski            // Available and in flight
3391b022d1937f5e9d9f87eef1097b4bf6f3b4043c9dMark Lobodzinski            if (qif_pair != queries_in_flight->end()) {
3392b022d1937f5e9d9f87eef1097b4bf6f3b4043c9dMark Lobodzinski                if (query_state_pair->second) {
3393b022d1937f5e9d9f87eef1097b4bf6f3b4043c9dMark Lobodzinski                    for (auto cmd_buffer : qif_pair->second) {
3394b022d1937f5e9d9f87eef1097b4bf6f3b4043c9dMark Lobodzinski                        auto cb = GetCBNode(dev_data, cmd_buffer);
3395b022d1937f5e9d9f87eef1097b4bf6f3b4043c9dMark Lobodzinski                        auto query_event_pair = cb->waitedEventsBeforeQueryReset.find(query);
3396b022d1937f5e9d9f87eef1097b4bf6f3b4043c9dMark Lobodzinski                        if (query_event_pair == cb->waitedEventsBeforeQueryReset.end()) {
3397b022d1937f5e9d9f87eef1097b4bf6f3b4043c9dMark Lobodzinski                            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
3398b022d1937f5e9d9f87eef1097b4bf6f3b4043c9dMark Lobodzinski                                            VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, __LINE__, DRAWSTATE_INVALID_QUERY, "DS",
3399b022d1937f5e9d9f87eef1097b4bf6f3b4043c9dMark Lobodzinski                                            "Cannot get query results on queryPool 0x%" PRIx64 " with index %d which is in flight.",
3400b022d1937f5e9d9f87eef1097b4bf6f3b4043c9dMark Lobodzinski                                            HandleToUint64(query_pool), first_query + i);
3401b022d1937f5e9d9f87eef1097b4bf6f3b4043c9dMark Lobodzinski                        }
3402b022d1937f5e9d9f87eef1097b4bf6f3b4043c9dMark Lobodzinski                    }
3403ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski                }
3404b022d1937f5e9d9f87eef1097b4bf6f3b4043c9dMark Lobodzinski            } else if (!query_state_pair->second) {  // Unavailable and Not in flight
34059fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0,
34069fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                                __LINE__, DRAWSTATE_INVALID_QUERY, "DS",
34079fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                                "Cannot get query results on queryPool 0x%" PRIx64 " with index %d which is unavailable.",
34089b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                HandleToUint64(query_pool), first_query + i);
34095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
3410b022d1937f5e9d9f87eef1097b4bf6f3b4043c9dMark Lobodzinski        } else {  // Uninitialized
3411b022d1937f5e9d9f87eef1097b4bf6f3b4043c9dMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0,
3412b022d1937f5e9d9f87eef1097b4bf6f3b4043c9dMark Lobodzinski                            __LINE__, DRAWSTATE_INVALID_QUERY, "DS",
3413b022d1937f5e9d9f87eef1097b4bf6f3b4043c9dMark Lobodzinski                            "Cannot get query results on queryPool 0x%" PRIx64
3414b022d1937f5e9d9f87eef1097b4bf6f3b4043c9dMark Lobodzinski                            " with index %d as data has not been collected for this index.",
3415b022d1937f5e9d9f87eef1097b4bf6f3b4043c9dMark Lobodzinski                            HandleToUint64(query_pool), first_query + i);
34165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
34175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
34189fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis    return skip;
34199fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis}
34209fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis
34219fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlisstatic void PostCallRecordGetQueryPoolResults(layer_data *dev_data, VkQueryPool query_pool, uint32_t first_query,
34229fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                                              uint32_t query_count,
34239fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                                              unordered_map<QueryObject, vector<VkCommandBuffer>> *queries_in_flight) {
34249fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis    for (uint32_t i = 0; i < query_count; ++i) {
34259fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis        QueryObject query = {query_pool, first_query + i};
34269fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis        auto qif_pair = queries_in_flight->find(query);
34279fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis        auto query_state_pair = dev_data->queryToStateMap.find(query);
34289fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis        if (query_state_pair != dev_data->queryToStateMap.end()) {
34299fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis            // Available and in flight
34309fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis            if (qif_pair != queries_in_flight->end() && query_state_pair != dev_data->queryToStateMap.end() &&
34319fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                query_state_pair->second) {
34329fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                for (auto cmd_buffer : qif_pair->second) {
34339a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                    auto cb = GetCBNode(dev_data, cmd_buffer);
34349fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                    auto query_event_pair = cb->waitedEventsBeforeQueryReset.find(query);
34359fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                    if (query_event_pair != cb->waitedEventsBeforeQueryReset.end()) {
34369fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                        for (auto event : query_event_pair->second) {
34379fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                            dev_data->eventMap[event].needsSignaled = true;
34389fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                        }
34399fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                    }
34409fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                }
34419fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis            }
34429fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis        }
34439fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis    }
34449fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis}
34459fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis
34469fdee42cd357379efb9aa27f90beb75d1f824955Tobin EhlisVKAPI_ATTR VkResult VKAPI_CALL GetQueryPoolResults(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount,
34479fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis                                                   size_t dataSize, void *pData, VkDeviceSize stride, VkQueryResultFlags flags) {
344856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
34499fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis    unordered_map<QueryObject, vector<VkCommandBuffer>> queries_in_flight;
3450ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
34519fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis    bool skip = PreCallValidateGetQueryPoolResults(dev_data, queryPool, firstQuery, queryCount, flags, &queries_in_flight);
3452b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
3453cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
34549fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis    VkResult result =
34559fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis        dev_data->dispatch_table.GetQueryPoolResults(device, queryPool, firstQuery, queryCount, dataSize, pData, stride, flags);
34569fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis    lock.lock();
34579fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis    PostCallRecordGetQueryPoolResults(dev_data, queryPool, firstQuery, queryCount, &queries_in_flight);
34589fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis    lock.unlock();
34599fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis    return result;
34605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
34615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
3462825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Return true if given ranges intersect, else false
3463825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Prereq : For both ranges, range->end - range->start > 0. This case should have already resulted
3464825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis//  in an error so not checking that here
3465825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// pad_ranges bool indicates a linear and non-linear comparison which requires padding
34663251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski// In the case where padding is required, if an alias is encountered then a validation error is reported and skip
34673251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski//  may be set by the callback function so caller should merge in skip value if padding case is possible.
34682ea938737c34152a86f5e453eaef7f77b45c0ea3Cort Stratton// This check can be skipped by passing skip_checks=true, for call sites outside the validation path.
34693251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinskistatic bool rangesIntersect(layer_data const *dev_data, MEMORY_RANGE const *range1, MEMORY_RANGE const *range2, bool *skip,
34702ea938737c34152a86f5e453eaef7f77b45c0ea3Cort Stratton                            bool skip_checks) {
34713251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    *skip = false;
3472825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    auto r1_start = range1->start;
3473825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    auto r1_end = range1->end;
3474825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    auto r2_start = range2->start;
3475825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    auto r2_end = range2->end;
3476825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    VkDeviceSize pad_align = 1;
3477825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    if (range1->linear != range2->linear) {
3478825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis        pad_align = dev_data->phys_dev_properties.properties.limits.bufferImageGranularity;
3479825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    }
3480cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if ((r1_end & ~(pad_align - 1)) < (r2_start & ~(pad_align - 1))) return false;
3481cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if ((r1_start & ~(pad_align - 1)) > (r2_end & ~(pad_align - 1))) return false;
348247aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski
34832ea938737c34152a86f5e453eaef7f77b45c0ea3Cort Stratton    if (!skip_checks && (range1->linear != range2->linear)) {
348453ecec26e80e4d18b57d24ed6eb91a3c9da4b95cTobin Ehlis        // In linear vs. non-linear case, warn of aliasing
3485825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis        const char *r1_linear_str = range1->linear ? "Linear" : "Non-linear";
3486825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis        const char *r1_type_str = range1->image ? "image" : "buffer";
3487825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis        const char *r2_linear_str = range2->linear ? "linear" : "non-linear";
3488825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis        const char *r2_type_str = range2->image ? "image" : "buffer";
3489825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis        auto obj_type = range1->image ? VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT : VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT;
34903251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        *skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, obj_type, range1->handle, 0,
34913251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                         MEMTRACK_INVALID_ALIASING, "MEM", "%s %s 0x%" PRIx64 " is aliased with %s %s 0x%" PRIx64
34923251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                                           " which may indicate a bug. For further info refer to the "
34933251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                                           "Buffer-Image Granularity section of the Vulkan specification. "
34943251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                                           "(https://www.khronos.org/registry/vulkan/specs/1.0-extensions/"
34953251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                                           "xhtml/vkspec.html#resources-bufferimagegranularity)",
34963251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                         r1_linear_str, r1_type_str, range1->handle, r2_linear_str, r2_type_str, range2->handle);
349747aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski    }
3498825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    // Ranges intersect
3499825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    return true;
350047aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski}
3501623548a271287ae55415e45e3c654ee66d4e79ffTobin Ehlis// Simplified rangesIntersect that calls above function to check range1 for intersection with offset & end addresses
3502c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinskibool rangesIntersect(layer_data const *dev_data, MEMORY_RANGE const *range1, VkDeviceSize offset, VkDeviceSize end) {
3503825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    // Create a local MEMORY_RANGE struct to wrap offset/size
3504825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    MEMORY_RANGE range_wrap;
3505825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    // Synch linear with range1 to avoid padding and potential validation error case
3506825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    range_wrap.linear = range1->linear;
3507825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    range_wrap.start = offset;
3508cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis    range_wrap.end = end;
3509825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    bool tmp_bool;
35102ea938737c34152a86f5e453eaef7f77b45c0ea3Cort Stratton    return rangesIntersect(dev_data, range1, &range_wrap, &tmp_bool, true);
3511825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis}
3512cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis// For given mem_info, set all ranges valid that intersect [offset-end] range
3513cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis// TODO : For ranges where there is no alias, we may want to create new buffer ranges that are valid
3514cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlisstatic void SetMemRangesValid(layer_data const *dev_data, DEVICE_MEM_INFO *mem_info, VkDeviceSize offset, VkDeviceSize end) {
3515cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis    bool tmp_bool = false;
3516f6e16b28b808a342cb92768001afa2cfeee08a11Tobin Ehlis    MEMORY_RANGE map_range = {};
3517cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis    map_range.linear = true;
3518cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis    map_range.start = offset;
3519cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis    map_range.end = end;
3520cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis    for (auto &handle_range_pair : mem_info->bound_ranges) {
35212ea938737c34152a86f5e453eaef7f77b45c0ea3Cort Stratton        if (rangesIntersect(dev_data, &handle_range_pair.second, &map_range, &tmp_bool, false)) {
3522cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis            // TODO : WARN here if tmp_bool true?
3523cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis            handle_range_pair.second.valid = true;
3524cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis        }
3525cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis    }
3526cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis}
35270ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton
35280ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Strattonstatic bool ValidateInsertMemoryRange(layer_data const *dev_data, uint64_t handle, DEVICE_MEM_INFO *mem_info,
35290ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton                                      VkDeviceSize memoryOffset, VkMemoryRequirements memRequirements, bool is_image,
35300ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton                                      bool is_linear, const char *api_name) {
35310ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton    bool skip = false;
35320ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton
35330ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton    MEMORY_RANGE range;
35340ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton    range.image = is_image;
35350ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton    range.handle = handle;
35360ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton    range.linear = is_linear;
35370ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton    range.valid = mem_info->global_valid;
35380ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton    range.memory = mem_info->mem;
35390ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton    range.start = memoryOffset;
35400ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton    range.size = memRequirements.size;
35410ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton    range.end = memoryOffset + memRequirements.size - 1;
35420ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton    range.aliases.clear();
35430ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton
35440ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton    // Check for aliasing problems.
35450ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton    for (auto &obj_range_pair : mem_info->bound_ranges) {
35460ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton        auto check_range = &obj_range_pair.second;
35470ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton        bool intersection_error = false;
35482ea938737c34152a86f5e453eaef7f77b45c0ea3Cort Stratton        if (rangesIntersect(dev_data, &range, check_range, &intersection_error, false)) {
35490ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton            skip |= intersection_error;
35500ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton            range.aliases.insert(check_range);
35510ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton        }
35520ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton    }
35530ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton
35540ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton    if (memoryOffset >= mem_info->alloc_info.allocationSize) {
3555315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        UNIQUE_VALIDATION_ERROR_CODE error_code = is_image ? VALIDATION_ERROR_1740082c : VALIDATION_ERROR_1700080e;
35560ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton        skip = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
35579b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                       HandleToUint64(mem_info->mem), __LINE__, error_code, "MEM",
35580ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton                       "In %s, attempting to bind memory (0x%" PRIxLEAST64 ") to object (0x%" PRIxLEAST64
35590ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton                       "), memoryOffset=0x%" PRIxLEAST64 " must be less than the memory allocation size 0x%" PRIxLEAST64 ". %s",
35609b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                       api_name, HandleToUint64(mem_info->mem), handle, memoryOffset, mem_info->alloc_info.allocationSize,
35619b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                       validation_error_map[error_code]);
35620ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton    }
35630ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton
35640ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton    return skip;
35650ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton}
35660ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton
3567825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Object with given handle is being bound to memory w/ given mem_info struct.
3568825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis//  Track the newly bound memory range with given memoryOffset
3569825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis//  Also scan any previous ranges, track aliased ranges with new range, and flag an error if a linear
3570825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis//  and non-linear range incorrectly overlap.
3571825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Return true if an error is flagged and the user callback returns "true", otherwise false
3572825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// is_image indicates an image object, otherwise handle is for a buffer
3573825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// is_linear indicates a buffer or linear image
35740ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Strattonstatic void InsertMemoryRange(layer_data const *dev_data, uint64_t handle, DEVICE_MEM_INFO *mem_info, VkDeviceSize memoryOffset,
35750ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton                              VkMemoryRequirements memRequirements, bool is_image, bool is_linear) {
35765360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis    MEMORY_RANGE range;
3577825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis
3578825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    range.image = is_image;
357947aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski    range.handle = handle;
3580825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    range.linear = is_linear;
3581f541bf53dee6daf82a4c8304354eac599a884d29Tobin Ehlis    range.valid = mem_info->global_valid;
3582825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    range.memory = mem_info->mem;
358347aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski    range.start = memoryOffset;
3584825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    range.size = memRequirements.size;
358547aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski    range.end = memoryOffset + memRequirements.size - 1;
35865360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis    range.aliases.clear();
35875360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis    // Update Memory aliasing
358875f4c8cec0996021a4258b9bf920a9e0fea4eac1Tobin 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
35895360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis    // inserted into map before loop to get the final ptr, then we may enter loop when not needed & we check range against itself
35905360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis    std::unordered_set<MEMORY_RANGE *> tmp_alias_ranges;
3591825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    for (auto &obj_range_pair : mem_info->bound_ranges) {
3592825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis        auto check_range = &obj_range_pair.second;
35935360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis        bool intersection_error = false;
35942ea938737c34152a86f5e453eaef7f77b45c0ea3Cort Stratton        if (rangesIntersect(dev_data, &range, check_range, &intersection_error, true)) {
3595825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis            range.aliases.insert(check_range);
35965360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis            tmp_alias_ranges.insert(check_range);
3597825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis        }
3598825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    }
35995360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis    mem_info->bound_ranges[handle] = std::move(range);
36005360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis    for (auto tmp_range : tmp_alias_ranges) {
36015360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis        tmp_range->aliases.insert(&mem_info->bound_ranges[handle]);
36025360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis    }
3603825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    if (is_image)
3604825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis        mem_info->bound_images.insert(handle);
3605825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    else
3606825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis        mem_info->bound_buffers.insert(handle);
360747aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski}
360847aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski
36090ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Strattonstatic bool ValidateInsertImageMemoryRange(layer_data const *dev_data, VkImage image, DEVICE_MEM_INFO *mem_info,
36100ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton                                           VkDeviceSize mem_offset, VkMemoryRequirements mem_reqs, bool is_linear,
36110ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton                                           const char *api_name) {
36129b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus    return ValidateInsertMemoryRange(dev_data, HandleToUint64(image), mem_info, mem_offset, mem_reqs, true, is_linear, api_name);
36130ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton}
36140ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Strattonstatic void InsertImageMemoryRange(layer_data const *dev_data, VkImage image, DEVICE_MEM_INFO *mem_info, VkDeviceSize mem_offset,
36150ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton                                   VkMemoryRequirements mem_reqs, bool is_linear) {
36169b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus    InsertMemoryRange(dev_data, HandleToUint64(image), mem_info, mem_offset, mem_reqs, true, is_linear);
3617825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis}
3618825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis
36190ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Strattonstatic bool ValidateInsertBufferMemoryRange(layer_data const *dev_data, VkBuffer buffer, DEVICE_MEM_INFO *mem_info,
36200ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton                                            VkDeviceSize mem_offset, VkMemoryRequirements mem_reqs, const char *api_name) {
36219b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus    return ValidateInsertMemoryRange(dev_data, HandleToUint64(buffer), mem_info, mem_offset, mem_reqs, false, true, api_name);
36220ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton}
36230ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Strattonstatic void InsertBufferMemoryRange(layer_data const *dev_data, VkBuffer buffer, DEVICE_MEM_INFO *mem_info, VkDeviceSize mem_offset,
36240ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton                                    VkMemoryRequirements mem_reqs) {
36259b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus    InsertMemoryRange(dev_data, HandleToUint64(buffer), mem_info, mem_offset, mem_reqs, false, true);
3626825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis}
3627825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis
3628825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Remove MEMORY_RANGE struct for give handle from bound_ranges of mem_info
3629825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis//  is_image indicates if handle is for image or buffer
3630825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis//  This function will also remove the handle-to-index mapping from the appropriate
3631825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis//  map and clean up any aliases for range being removed.
3632825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlisstatic void RemoveMemoryRange(uint64_t handle, DEVICE_MEM_INFO *mem_info, bool is_image) {
3633825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    auto erase_range = &mem_info->bound_ranges[handle];
3634825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    for (auto alias_range : erase_range->aliases) {
3635825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis        alias_range->aliases.erase(erase_range);
363647aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski    }
36375360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis    erase_range->aliases.clear();
3638825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis    mem_info->bound_ranges.erase(handle);
36391cba4e1b5940c6818572e05dcad5a3a47fafbc9eTobin Ehlis    if (is_image) {
3640825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis        mem_info->bound_images.erase(handle);
36411cba4e1b5940c6818572e05dcad5a3a47fafbc9eTobin Ehlis    } else {
3642825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis        mem_info->bound_buffers.erase(handle);
36431cba4e1b5940c6818572e05dcad5a3a47fafbc9eTobin Ehlis    }
364447aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski}
364547aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski
3646842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinskivoid RemoveBufferMemoryRange(uint64_t handle, DEVICE_MEM_INFO *mem_info) { RemoveMemoryRange(handle, mem_info, false); }
3647825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis
36488c59133586421be878d393799b30044497f77727Mark Lobodzinskivoid RemoveImageMemoryRange(uint64_t handle, DEVICE_MEM_INFO *mem_info) { RemoveMemoryRange(handle, mem_info, true); }
3649825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis
3650bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyBuffer(VkDevice device, VkBuffer buffer, const VkAllocationCallbacks *pAllocator) {
365156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
3652e1056daefb39e3a3fed0088874725c56a1359e54Tobin Ehlis    BUFFER_STATE *buffer_state = nullptr;
3653e1056daefb39e3a3fed0088874725c56a1359e54Tobin Ehlis    VK_OBJECT obj_struct;
3654ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
3655e1056daefb39e3a3fed0088874725c56a1359e54Tobin Ehlis    bool skip = PreCallValidateDestroyBuffer(dev_data, buffer, &buffer_state, &obj_struct);
3656e1056daefb39e3a3fed0088874725c56a1359e54Tobin Ehlis    if (!skip) {
3657b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.unlock();
36584a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.DestroyBuffer(device, buffer, pAllocator);
3659e1056daefb39e3a3fed0088874725c56a1359e54Tobin Ehlis        lock.lock();
3660405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        if (buffer != VK_NULL_HANDLE) {
3661405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour            PostCallRecordDestroyBuffer(dev_data, buffer, buffer_state, obj_struct);
3662405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        }
366347aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski    }
36645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
36655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
3666bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyBufferView(VkDevice device, VkBufferView bufferView, const VkAllocationCallbacks *pAllocator) {
366756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
3668f61017735c3291a2665487f2bac310578fc60a68Tobin Ehlis    // Common data objects used pre & post call
36698e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis    BUFFER_VIEW_STATE *buffer_view_state = nullptr;
36708e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis    VK_OBJECT obj_struct;
3671ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
36728e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis    // Validate state before calling down chain, update common data if we'll be calling down chain
36738e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis    bool skip = PreCallValidateDestroyBufferView(dev_data, bufferView, &buffer_view_state, &obj_struct);
367438e26abbaa884eb48bfec4ddb4e0ae2c90634e06Tobin Ehlis    if (!skip) {
367538e26abbaa884eb48bfec4ddb4e0ae2c90634e06Tobin Ehlis        lock.unlock();
36764a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.DestroyBufferView(device, bufferView, pAllocator);
36778e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis        lock.lock();
3678405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        if (bufferView != VK_NULL_HANDLE) {
3679405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour            PostCallRecordDestroyBufferView(dev_data, bufferView, buffer_view_state, obj_struct);
3680405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        }
36815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
36825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
36835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
36842a0dd15a44bf665c97a3ff6adcbe7fe5853cdf60Tobin EhlisVKAPI_ATTR void VKAPI_CALL DestroyImage(VkDevice device, VkImage image, const VkAllocationCallbacks *pAllocator) {
368556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
36861facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis    IMAGE_STATE *image_state = nullptr;
36872a0dd15a44bf665c97a3ff6adcbe7fe5853cdf60Tobin Ehlis    VK_OBJECT obj_struct;
3688ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
36892a0dd15a44bf665c97a3ff6adcbe7fe5853cdf60Tobin Ehlis    bool skip = PreCallValidateDestroyImage(dev_data, image, &image_state, &obj_struct);
36902a0dd15a44bf665c97a3ff6adcbe7fe5853cdf60Tobin Ehlis    if (!skip) {
3691f940225c9e5e3e14b3f5a32d3ea360b585614600Tobin Ehlis        lock.unlock();
36924a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.DestroyImage(device, image, pAllocator);
36932a0dd15a44bf665c97a3ff6adcbe7fe5853cdf60Tobin Ehlis        lock.lock();
3694405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        if (image != VK_NULL_HANDLE) {
3695405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour            PostCallRecordDestroyImage(dev_data, image, image_state, obj_struct);
3696405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        }
36975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
36985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
36995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
37004261f1e2c91c90ce040ab36a13c9d92f6e988f10Mark Lobodzinskistatic bool ValidateMemoryTypes(const layer_data *dev_data, const DEVICE_MEM_INFO *mem_info, const uint32_t memory_type_bits,
3701f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen                                const char *funcName, UNIQUE_VALIDATION_ERROR_CODE msgCode) {
37023251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
3703de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis    if (((1 << mem_info->alloc_info.memoryTypeIndex) & memory_type_bits) == 0) {
37043251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
37059b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                       HandleToUint64(mem_info->mem), __LINE__, msgCode, "MT",
37063251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                       "%s(): MemoryRequirements->memoryTypeBits (0x%X) for this object type are not compatible with the memory "
37073251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                       "type (0x%X) of this memory object 0x%" PRIx64 ". %s",
37089b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                       funcName, memory_type_bits, mem_info->alloc_info.memoryTypeIndex, HandleToUint64(mem_info->mem),
37099b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                       validation_error_map[msgCode]);
37104261f1e2c91c90ce040ab36a13c9d92f6e988f10Mark Lobodzinski    }
37113251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
37124261f1e2c91c90ce040ab36a13c9d92f6e988f10Mark Lobodzinski}
37134261f1e2c91c90ce040ab36a13c9d92f6e988f10Mark Lobodzinski
3714160335c453ec51cc48bdef78e8befdb3c86ff292Cort Strattonstatic bool PreCallValidateBindBufferMemory(layer_data *dev_data, VkBuffer buffer, BUFFER_STATE *buffer_state, VkDeviceMemory mem,
3715160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton                                            VkDeviceSize memoryOffset) {
37169207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton    bool skip = false;
37175cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis    if (buffer_state) {
3718ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes        unique_lock_t lock(global_lock);
37199207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton        // Track objects tied to memory
37209b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus        uint64_t buffer_handle = HandleToUint64(buffer);
37217a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski        skip = ValidateSetMemBinding(dev_data, mem, buffer_handle, kVulkanObjectTypeBuffer, "vkBindBufferMemory()");
37222eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis        if (!buffer_state->memory_requirements_checked) {
37232eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis            // There's not an explicit requirement in the spec to call vkGetBufferMemoryRequirements() prior to calling
37249207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton            // BindBufferMemory, but it's implied in that memory being bound must conform with VkMemoryRequirements from
37259207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton            // vkGetBufferMemoryRequirements()
37269207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT,
37279207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton                            buffer_handle, __LINE__, DRAWSTATE_INVALID_BUFFER, "DS",
37289207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton                            "vkBindBufferMemory(): Binding memory to buffer 0x%" PRIxLEAST64
37299207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton                            " but vkGetBufferMemoryRequirements() has not been called on that buffer.",
37309207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton                            buffer_handle);
37312eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis            // Make the call for them so we can verify the state
37322eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis            lock.unlock();
37339207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton            dev_data->dispatch_table.GetBufferMemoryRequirements(dev_data->device, buffer, &buffer_state->requirements);
37342eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis            lock.lock();
37352eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis        }
373647aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski
37370ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton        // Validate bound memory range information
37389a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto mem_info = GetMemObjInfo(dev_data, mem);
373957fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis        if (mem_info) {
37400ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton            skip |= ValidateInsertBufferMemoryRange(dev_data, buffer, mem_info, memoryOffset, buffer_state->requirements,
37410ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton                                                    "vkBindBufferMemory()");
37429207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton            skip |= ValidateMemoryTypes(dev_data, mem_info, buffer_state->requirements.memoryTypeBits, "vkBindBufferMemory()",
3743315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                        VALIDATION_ERROR_17000816);
374447aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski        }
374547aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski
37462c905c8b5aca814df6c680348145ca48885f9f69Dustin Graves        // Validate memory requirements alignment
374716769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton        if (SafeModulo(memoryOffset, buffer_state->requirements.alignment) != 0) {
3748f60e41965223825191505eebc96491bb52e494a2Cort Stratton            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT,
3749315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            buffer_handle, __LINE__, VALIDATION_ERROR_17000818, "DS",
37509207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton                            "vkBindBufferMemory(): memoryOffset is 0x%" PRIxLEAST64
37519207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton                            " but must be an integer multiple of the "
37529207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton                            "VkMemoryRequirements::alignment value 0x%" PRIxLEAST64
37539207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton                            ", returned from a call to vkGetBufferMemoryRequirements with buffer. %s",
3754315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            memoryOffset, buffer_state->requirements.alignment, validation_error_map[VALIDATION_ERROR_17000818]);
37552c905c8b5aca814df6c680348145ca48885f9f69Dustin Graves        }
3756ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller
3757160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton        // Validate memory requirements size
3758160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton        if (buffer_state->requirements.size > (mem_info->alloc_info.allocationSize - memoryOffset)) {
3759160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT,
3760315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            buffer_handle, __LINE__, VALIDATION_ERROR_1700081a, "DS",
3761160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton                            "vkBindBufferMemory(): memory size minus memoryOffset is 0x%" PRIxLEAST64
3762160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton                            " but must be at least as large as "
3763160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton                            "VkMemoryRequirements::size value 0x%" PRIxLEAST64
3764160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton                            ", returned from a call to vkGetBufferMemoryRequirements with buffer. %s",
3765160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton                            mem_info->alloc_info.allocationSize - memoryOffset, buffer_state->requirements.size,
3766315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            validation_error_map[VALIDATION_ERROR_1700081a]);
3767160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton        }
3768160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton
37692c905c8b5aca814df6c680348145ca48885f9f69Dustin Graves        // Validate device limits alignments
3770ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller        static const VkBufferUsageFlagBits usage_list[3] = {
3771ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller            static_cast<VkBufferUsageFlagBits>(VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT),
3772bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski            VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT};
3773bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        static const char *memory_type[3] = {"texel", "uniform", "storage"};
3774bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        static const char *offset_name[3] = {"minTexelBufferOffsetAlignment", "minUniformBufferOffsetAlignment",
3775bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                             "minStorageBufferOffsetAlignment"};
3776cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski
37779207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton        // TODO:  vk_validation_stats.py cannot abide braces immediately preceding or following a validation error enum
3778cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        // clang-format off
3779315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        static const UNIQUE_VALIDATION_ERROR_CODE msgCode[3] = { VALIDATION_ERROR_17000810, VALIDATION_ERROR_17000812,
3780315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis            VALIDATION_ERROR_17000814 };
3781cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        // clang-format on
3782ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller
3783ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller        // Keep this one fresh!
3784ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller        const VkDeviceSize offset_requirement[3] = {
3785ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller            dev_data->phys_dev_properties.properties.limits.minTexelBufferOffsetAlignment,
3786ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller            dev_data->phys_dev_properties.properties.limits.minUniformBufferOffsetAlignment,
3787bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski            dev_data->phys_dev_properties.properties.limits.minStorageBufferOffsetAlignment};
37888718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis        VkBufferUsageFlags usage = dev_data->bufferMap[buffer].get()->createInfo.usage;
3789ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller
3790ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller        for (int i = 0; i < 3; i++) {
3791ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller            if (usage & usage_list[i]) {
379216769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton                if (SafeModulo(memoryOffset, offset_requirement[i]) != 0) {
37939207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton                    skip |= log_msg(
3794f60e41965223825191505eebc96491bb52e494a2Cort Stratton                        dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, buffer_handle,
3795cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                        __LINE__, msgCode[i], "DS", "vkBindBufferMemory(): %s memoryOffset is 0x%" PRIxLEAST64
3796cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                                                    " but must be a multiple of "
3797cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                                                    "device limit %s 0x%" PRIxLEAST64 ". %s",
3798cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                        memory_type[i], memoryOffset, offset_name[i], offset_requirement[i], validation_error_map[msgCode[i]]);
3799ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller                }
38002c905c8b5aca814df6c680348145ca48885f9f69Dustin Graves            }
38012c905c8b5aca814df6c680348145ca48885f9f69Dustin Graves        }
38025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
38039207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton    return skip;
38049207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton}
38059207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton
3806160335c453ec51cc48bdef78e8befdb3c86ff292Cort Strattonstatic void PostCallRecordBindBufferMemory(layer_data *dev_data, VkBuffer buffer, BUFFER_STATE *buffer_state, VkDeviceMemory mem,
3807160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton                                           VkDeviceSize memoryOffset) {
38089207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton    if (buffer_state) {
3809ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes        unique_lock_t lock(global_lock);
38100ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton        // Track bound memory range information
38110ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton        auto mem_info = GetMemObjInfo(dev_data, mem);
38120ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton        if (mem_info) {
38130ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton            InsertBufferMemoryRange(dev_data, buffer, mem_info, memoryOffset, buffer_state->requirements);
38140ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton        }
38150ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton
3816c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton        // Track objects tied to memory
38179b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus        uint64_t buffer_handle = HandleToUint64(buffer);
38187a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski        SetMemBinding(dev_data, mem, buffer_handle, kVulkanObjectTypeBuffer, "vkBindBufferMemory()");
3819c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton
38209207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton        buffer_state->binding.mem = mem;
38219207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton        buffer_state->binding.offset = memoryOffset;
38229207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton        buffer_state->binding.size = buffer_state->requirements.size;
38239207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton    }
38249207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton}
38259207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton
38269207132ef623d47fcbdfeb9ebc796eade35a2f4cCort StrattonVKAPI_ATTR VkResult VKAPI_CALL BindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory mem, VkDeviceSize memoryOffset) {
38279207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
38289207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
3829160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton    auto buffer_state = GetBufferState(dev_data, buffer);
3830160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton    bool skip = PreCallValidateBindBufferMemory(dev_data, buffer, buffer_state, mem, memoryOffset);
38319207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton    if (!skip) {
38324a0754042cf090e131e9e769d8a3633c228625beChris Forbes        result = dev_data->dispatch_table.BindBufferMemory(device, buffer, mem, memoryOffset);
38339207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton        if (result == VK_SUCCESS) {
3834160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton            PostCallRecordBindBufferMemory(dev_data, buffer, buffer_state, mem, memoryOffset);
38359207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton        }
38365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
38375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
38385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
38395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
3840bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL GetBufferMemoryRequirements(VkDevice device, VkBuffer buffer,
3841bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                       VkMemoryRequirements *pMemoryRequirements) {
384256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
384315caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis    dev_data->dispatch_table.GetBufferMemoryRequirements(device, buffer, pMemoryRequirements);
3844cd3fe6716d6c206368a0c404fcd25332860fd573Jean-François Marquis    BUFFER_STATE* buffer_state;
3845cd3fe6716d6c206368a0c404fcd25332860fd573Jean-François Marquis    {
3846cd3fe6716d6c206368a0c404fcd25332860fd573Jean-François Marquis        unique_lock_t lock(global_lock);
3847cd3fe6716d6c206368a0c404fcd25332860fd573Jean-François Marquis        buffer_state = GetBufferState(dev_data, buffer);
3848cd3fe6716d6c206368a0c404fcd25332860fd573Jean-François Marquis    }
384915caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis    if (buffer_state) {
385015caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis        buffer_state->requirements = *pMemoryRequirements;
38512eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis        buffer_state->memory_requirements_checked = true;
385215caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis    }
38535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
38545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
3855bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL GetImageMemoryRequirements(VkDevice device, VkImage image, VkMemoryRequirements *pMemoryRequirements) {
385656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
385715caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis    dev_data->dispatch_table.GetImageMemoryRequirements(device, image, pMemoryRequirements);
3858cd3fe6716d6c206368a0c404fcd25332860fd573Jean-François Marquis    IMAGE_STATE* image_state;
3859cd3fe6716d6c206368a0c404fcd25332860fd573Jean-François Marquis    {
3860cd3fe6716d6c206368a0c404fcd25332860fd573Jean-François Marquis        unique_lock_t lock(global_lock);
3861cd3fe6716d6c206368a0c404fcd25332860fd573Jean-François Marquis        image_state = GetImageState(dev_data, image);
3862cd3fe6716d6c206368a0c404fcd25332860fd573Jean-François Marquis    }
386315caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis    if (image_state) {
386415caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis        image_state->requirements = *pMemoryRequirements;
38652eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis        image_state->memory_requirements_checked = true;
386615caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis    }
38675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
3868593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis
3869bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyImageView(VkDevice device, VkImageView imageView, const VkAllocationCallbacks *pAllocator) {
387056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
3871f61017735c3291a2665487f2bac310578fc60a68Tobin Ehlis    // Common data objects used pre & post call
3872f61017735c3291a2665487f2bac310578fc60a68Tobin Ehlis    IMAGE_VIEW_STATE *image_view_state = nullptr;
3873f61017735c3291a2665487f2bac310578fc60a68Tobin Ehlis    VK_OBJECT obj_struct;
3874ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
3875f61017735c3291a2665487f2bac310578fc60a68Tobin Ehlis    bool skip = PreCallValidateDestroyImageView(dev_data, imageView, &image_view_state, &obj_struct);
3876d85c42a6c1d6ad7a6f684c5bd793aab482b7705cTobin Ehlis    if (!skip) {
3877d85c42a6c1d6ad7a6f684c5bd793aab482b7705cTobin Ehlis        lock.unlock();
38784a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.DestroyImageView(device, imageView, pAllocator);
3879f61017735c3291a2665487f2bac310578fc60a68Tobin Ehlis        lock.lock();
3880405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        if (imageView != VK_NULL_HANDLE) {
3881405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour            PostCallRecordDestroyImageView(dev_data, imageView, image_view_state, obj_struct);
3882405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        }
3883d85c42a6c1d6ad7a6f684c5bd793aab482b7705cTobin Ehlis    }
38845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
38855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
3886bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyShaderModule(VkDevice device, VkShaderModule shaderModule,
3887bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                               const VkAllocationCallbacks *pAllocator) {
388856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
3889918c283ac4f8c604b79abd0c8b5706d2a7352a34Chris Forbes
3890ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
389151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    dev_data->shaderModuleMap.erase(shaderModule);
3892b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
3893918c283ac4f8c604b79abd0c8b5706d2a7352a34Chris Forbes
389451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis    dev_data->dispatch_table.DestroyShaderModule(device, shaderModule, pAllocator);
38955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
38965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
38974c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlisstatic bool PreCallValidateDestroyPipeline(layer_data *dev_data, VkPipeline pipeline, PIPELINE_STATE **pipeline_state,
38988bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis                                           VK_OBJECT *obj_struct) {
389994165f5005d1fa37801d49067fe7751789b89d27Tobin Ehlis    *pipeline_state = getPipelineState(dev_data, pipeline);
39009b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus    *obj_struct = {HandleToUint64(pipeline), kVulkanObjectTypePipeline};
3901cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.destroy_pipeline) return false;
39028bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis    bool skip = false;
39038bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis    if (*pipeline_state) {
390469ea2c79d7b3f9c987671a10686afac066b275b9Mike Schuchardt        skip |= ValidateObjectNotInUse(dev_data, *pipeline_state, *obj_struct, "vkDestroyPipeline", VALIDATION_ERROR_25c005fa);
39058bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis    }
39068bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis    return skip;
39078bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis}
39088bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis
39094c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlisstatic void PostCallRecordDestroyPipeline(layer_data *dev_data, VkPipeline pipeline, PIPELINE_STATE *pipeline_state,
39108bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis                                          VK_OBJECT obj_struct) {
39118bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis    // Any bound cmd buffers are now invalid
391239c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis    invalidateCommandBuffers(dev_data, pipeline_state->cb_bindings, obj_struct);
39138bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis    dev_data->pipelineMap.erase(pipeline);
39148bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis}
39158bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis
3916bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyPipeline(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks *pAllocator) {
391756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
39184c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis    PIPELINE_STATE *pipeline_state = nullptr;
39198bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis    VK_OBJECT obj_struct;
3920ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
39218bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis    bool skip = PreCallValidateDestroyPipeline(dev_data, pipeline, &pipeline_state, &obj_struct);
3922f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis    if (!skip) {
3923f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis        lock.unlock();
39244a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.DestroyPipeline(device, pipeline, pAllocator);
39258bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis        lock.lock();
3926405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        if (pipeline != VK_NULL_HANDLE) {
3927405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour            PostCallRecordDestroyPipeline(dev_data, pipeline, pipeline_state, obj_struct);
3928405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        }
3929f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis    }
39305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
39315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
3932bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyPipelineLayout(VkDevice device, VkPipelineLayout pipelineLayout,
3933bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                 const VkAllocationCallbacks *pAllocator) {
393456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
3935ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
39366792ea7cc0ce5fa64b7bd6c946460608cbda91c7Tobin Ehlis    dev_data->pipelineLayoutMap.erase(pipelineLayout);
3937e28cddb35c63274c13873b9a7060ad43b255c6f1Tobin Ehlis    lock.unlock();
3938e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis
39394a0754042cf090e131e9e769d8a3633c228625beChris Forbes    dev_data->dispatch_table.DestroyPipelineLayout(device, pipelineLayout, pAllocator);
39405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
39415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
3942d31a44af6da568692a73201825459689c9431867Tobin Ehlisstatic bool PreCallValidateDestroySampler(layer_data *dev_data, VkSampler sampler, SAMPLER_STATE **sampler_state,
3943806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis                                          VK_OBJECT *obj_struct) {
39449a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    *sampler_state = GetSamplerState(dev_data, sampler);
39459b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus    *obj_struct = {HandleToUint64(sampler), kVulkanObjectTypeSampler};
3946cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.destroy_sampler) return false;
3947806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis    bool skip = false;
3948806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis    if (*sampler_state) {
394969ea2c79d7b3f9c987671a10686afac066b275b9Mike Schuchardt        skip |= ValidateObjectNotInUse(dev_data, *sampler_state, *obj_struct, "vkDestroySampler", VALIDATION_ERROR_26600874);
3950806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis    }
3951806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis    return skip;
3952806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis}
3953806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis
3954d31a44af6da568692a73201825459689c9431867Tobin Ehlisstatic void PostCallRecordDestroySampler(layer_data *dev_data, VkSampler sampler, SAMPLER_STATE *sampler_state,
3955806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis                                         VK_OBJECT obj_struct) {
3956806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis    // Any bound cmd buffers are now invalid
3957cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (sampler_state) invalidateCommandBuffers(dev_data, sampler_state->cb_bindings, obj_struct);
3958806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis    dev_data->samplerMap.erase(sampler);
3959806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis}
3960806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis
3961bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroySampler(VkDevice device, VkSampler sampler, const VkAllocationCallbacks *pAllocator) {
396256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
3963d31a44af6da568692a73201825459689c9431867Tobin Ehlis    SAMPLER_STATE *sampler_state = nullptr;
3964806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis    VK_OBJECT obj_struct;
3965ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
3966806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis    bool skip = PreCallValidateDestroySampler(dev_data, sampler, &sampler_state, &obj_struct);
3967f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis    if (!skip) {
3968f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis        lock.unlock();
39694a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.DestroySampler(device, sampler, pAllocator);
3970806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis        lock.lock();
3971405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        if (sampler != VK_NULL_HANDLE) {
3972405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour            PostCallRecordDestroySampler(dev_data, sampler, sampler_state, obj_struct);
3973405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        }
3974f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis    }
39755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
39765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
397779c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlisstatic void PostCallRecordDestroyDescriptorSetLayout(layer_data *dev_data, VkDescriptorSetLayout ds_layout) {
397879c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlis    dev_data->descriptorSetLayoutMap.erase(ds_layout);
397979c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlis}
398079c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlis
3981bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyDescriptorSetLayout(VkDevice device, VkDescriptorSetLayout descriptorSetLayout,
3982bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                      const VkAllocationCallbacks *pAllocator) {
398356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
398479c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlis    dev_data->dispatch_table.DestroyDescriptorSetLayout(device, descriptorSetLayout, pAllocator);
3985ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
398679c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlis    PostCallRecordDestroyDescriptorSetLayout(dev_data, descriptorSetLayout);
39875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
39885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
3989c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlisstatic bool PreCallValidateDestroyDescriptorPool(layer_data *dev_data, VkDescriptorPool pool,
3990a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis                                                 DESCRIPTOR_POOL_STATE **desc_pool_state, VK_OBJECT *obj_struct) {
39919a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    *desc_pool_state = GetDescriptorPoolState(dev_data, pool);
39929b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus    *obj_struct = {HandleToUint64(pool), kVulkanObjectTypeDescriptorPool};
3993cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.destroy_descriptor_pool) return false;
3994c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis    bool skip = false;
3995c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis    if (*desc_pool_state) {
399669ea2c79d7b3f9c987671a10686afac066b275b9Mike Schuchardt        skip |=
399769ea2c79d7b3f9c987671a10686afac066b275b9Mike Schuchardt            ValidateObjectNotInUse(dev_data, *desc_pool_state, *obj_struct, "vkDestroyDescriptorPool", VALIDATION_ERROR_2440025e);
3998c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis    }
3999c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis    return skip;
4000c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis}
4001c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis
4002c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlisstatic void PostCallRecordDestroyDescriptorPool(layer_data *dev_data, VkDescriptorPool descriptorPool,
4003a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis                                                DESCRIPTOR_POOL_STATE *desc_pool_state, VK_OBJECT obj_struct) {
4004c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis    // Any bound cmd buffers are now invalid
400539c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis    invalidateCommandBuffers(dev_data, desc_pool_state->cb_bindings, obj_struct);
4006c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis    // Free sets that were in this pool
4007c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis    for (auto ds : desc_pool_state->sets) {
4008c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis        freeDescriptorSet(dev_data, ds);
4009c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis    }
4010c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis    dev_data->descriptorPoolMap.erase(descriptorPool);
4011ee7e96d032744c1db89cab21362ac8ecad6eec5aGabríel Arthúr Pétursson    delete desc_pool_state;
4012c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis}
4013c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis
4014bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool,
4015bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                 const VkAllocationCallbacks *pAllocator) {
401656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
4017a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis    DESCRIPTOR_POOL_STATE *desc_pool_state = nullptr;
4018c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis    VK_OBJECT obj_struct;
4019ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
4020c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis    bool skip = PreCallValidateDestroyDescriptorPool(dev_data, descriptorPool, &desc_pool_state, &obj_struct);
4021c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis    if (!skip) {
4022c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis        lock.unlock();
4023c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis        dev_data->dispatch_table.DestroyDescriptorPool(device, descriptorPool, pAllocator);
4024c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis        lock.lock();
4025405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        if (descriptorPool != VK_NULL_HANDLE) {
4026405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour            PostCallRecordDestroyDescriptorPool(dev_data, descriptorPool, desc_pool_state, obj_struct);
4027405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        }
4028c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis    }
40295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
40303251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski// Verify cmdBuffer in given cb_node is not in global in-flight set, and return skip result
4031bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis//  If this is a secondary command buffer, then make sure its primary is also in-flight
4032bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis//  If primary is not in-flight, then remove secondary from global in-flight set
4033bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis// This function is only valid at a point when cmdBuffer is being reset or freed
4034cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlisstatic bool checkCommandBufferInFlight(layer_data *dev_data, const GLOBAL_CB_NODE *cb_node, const char *action,
4035cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlis                                       UNIQUE_VALIDATION_ERROR_CODE error_code) {
40363251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
4037a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes    if (cb_node->in_use.load()) {
4038a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
4039a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes                        HandleToUint64(cb_node->commandBuffer), __LINE__, error_code, "DS",
4040a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes                        "Attempt to %s command buffer (0x%p) which is in use. %s", action, cb_node->commandBuffer,
4041a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes                        validation_error_map[error_code]);
4042bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis    }
40433251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
4044bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis}
4045a964cad279f9749cd9ebfc7555247ff3bff26d53Chris Forbes
4046bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis// Iterate over all cmdBuffers in given commandPool and verify that each is not in use
4047cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlisstatic bool checkCommandBuffersInFlight(layer_data *dev_data, COMMAND_POOL_NODE *pPool, const char *action,
4048cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlis                                        UNIQUE_VALIDATION_ERROR_CODE error_code) {
40493251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
4050a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes    for (auto cmd_buffer : pPool->commandBuffers) {
4051a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes        skip |= checkCommandBufferInFlight(dev_data, GetCBNode(dev_data, cmd_buffer), action, error_code);
4052bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis    }
40533251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
4054bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis}
40555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
40567cb00fa300f2563ae3e8eb506bca912c11216953John Zulauf// Free all command buffers in given list, removing all references/links to them using ResetCommandBufferState
4057c8d1e7bb99c01ae0c2824fe7286fb0a1173de589John Zulaufstatic void FreeCommandBufferStates(layer_data *dev_data, COMMAND_POOL_NODE *pool_state, const uint32_t command_buffer_count,
4058c8d1e7bb99c01ae0c2824fe7286fb0a1173de589John Zulauf                                    const VkCommandBuffer *command_buffers) {
4059c8d1e7bb99c01ae0c2824fe7286fb0a1173de589John Zulauf    for (uint32_t i = 0; i < command_buffer_count; i++) {
4060c8d1e7bb99c01ae0c2824fe7286fb0a1173de589John Zulauf        auto cb_state = GetCBNode(dev_data, command_buffers[i]);
4061c8d1e7bb99c01ae0c2824fe7286fb0a1173de589John Zulauf        // Remove references to command buffer's state and delete
4062c8d1e7bb99c01ae0c2824fe7286fb0a1173de589John Zulauf        if (cb_state) {
4063c8d1e7bb99c01ae0c2824fe7286fb0a1173de589John Zulauf            // reset prior to delete, removing various references to it.
4064c8d1e7bb99c01ae0c2824fe7286fb0a1173de589John Zulauf            // TODO: fix this, it's insane.
40657cb00fa300f2563ae3e8eb506bca912c11216953John Zulauf            ResetCommandBufferState(dev_data, cb_state->commandBuffer);
4066c8d1e7bb99c01ae0c2824fe7286fb0a1173de589John Zulauf            // Remove the cb_state's references from layer_data and COMMAND_POOL_NODE
4067c8d1e7bb99c01ae0c2824fe7286fb0a1173de589John Zulauf            dev_data->commandBufferMap.erase(cb_state->commandBuffer);
4068c8d1e7bb99c01ae0c2824fe7286fb0a1173de589John Zulauf            pool_state->commandBuffers.erase(command_buffers[i]);
4069c8d1e7bb99c01ae0c2824fe7286fb0a1173de589John Zulauf            delete cb_state;
4070c8d1e7bb99c01ae0c2824fe7286fb0a1173de589John Zulauf        }
4071c8d1e7bb99c01ae0c2824fe7286fb0a1173de589John Zulauf    }
4072c8d1e7bb99c01ae0c2824fe7286fb0a1173de589John Zulauf}
4073c8d1e7bb99c01ae0c2824fe7286fb0a1173de589John Zulauf
4074bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL FreeCommandBuffers(VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount,
4075bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                              const VkCommandBuffer *pCommandBuffers) {
407656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
40773251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
4078ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
4079c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes
40805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < commandBufferCount; i++) {
40819a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto cb_node = GetCBNode(dev_data, pCommandBuffers[i]);
40825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // Delete CB information structure, and remove from commandBufferMap
40839f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis        if (cb_node) {
4084315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis            skip |= checkCommandBufferInFlight(dev_data, cb_node, "free", VALIDATION_ERROR_2840005e);
4085c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes        }
4086c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes    }
4087c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes
40883251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (skip) return;
4089c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes
40909a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto pPool = GetCommandPoolNode(dev_data, commandPool);
4091c8d1e7bb99c01ae0c2824fe7286fb0a1173de589John Zulauf    FreeCommandBufferStates(dev_data, pPool, commandBufferCount, pCommandBuffers);
4092b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
4093e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis
40944a0754042cf090e131e9e769d8a3633c228625beChris Forbes    dev_data->dispatch_table.FreeCommandBuffers(device, commandPool, commandBufferCount, pCommandBuffers);
40955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
40965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
409789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateCommandPool(VkDevice device, const VkCommandPoolCreateInfo *pCreateInfo,
4098bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                 const VkAllocationCallbacks *pAllocator, VkCommandPool *pCommandPool) {
409956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
41005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
41014a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.CreateCommandPool(device, pCreateInfo, pAllocator, pCommandPool);
41025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
41035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
4104ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes        lock_guard_t lock(global_lock);
41055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        dev_data->commandPoolMap[*pCommandPool].createFlags = pCreateInfo->flags;
41065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        dev_data->commandPoolMap[*pCommandPool].queueFamilyIndex = pCreateInfo->queueFamilyIndex;
41075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
41085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
41095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
41105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
411189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateQueryPool(VkDevice device, const VkQueryPoolCreateInfo *pCreateInfo,
411289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                               const VkAllocationCallbacks *pAllocator, VkQueryPool *pQueryPool) {
411356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
41140c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis    bool skip = false;
41150c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis    if (pCreateInfo && pCreateInfo->queryType == VK_QUERY_TYPE_PIPELINE_STATISTICS) {
41160c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis        if (!dev_data->enabled_features.pipelineStatisticsQuery) {
41170c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0,
4118315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            __LINE__, VALIDATION_ERROR_11c0062e, "DS",
41190c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis                            "Query pool with type VK_QUERY_TYPE_PIPELINE_STATISTICS created on a device "
41200c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis                            "with VkDeviceCreateInfo.pEnabledFeatures.pipelineStatisticsQuery == VK_FALSE. %s",
4121315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            validation_error_map[VALIDATION_ERROR_11c0062e]);
41220c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis        }
41230c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis    }
41240c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis
41250c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
41260c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis    if (!skip) {
41270c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis        result = dev_data->dispatch_table.CreateQueryPool(device, pCreateInfo, pAllocator, pQueryPool);
41280c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis    }
41295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (result == VK_SUCCESS) {
4130ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes        lock_guard_t lock(global_lock);
4131eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis        QUERY_POOL_NODE *qp_node = &dev_data->queryPoolMap[*pQueryPool];
4132eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis        qp_node->createInfo = *pCreateInfo;
41335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
41345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
41355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
41365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
4137c8d1e7bb99c01ae0c2824fe7286fb0a1173de589John Zulaufstatic bool PreCallValidateDestroyCommandPool(layer_data *dev_data, VkCommandPool pool) {
4138c8d1e7bb99c01ae0c2824fe7286fb0a1173de589John Zulauf    COMMAND_POOL_NODE *cp_state = GetCommandPoolNode(dev_data, pool);
4139cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.destroy_command_pool) return false;
41405f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis    bool skip = false;
4141c8d1e7bb99c01ae0c2824fe7286fb0a1173de589John Zulauf    if (cp_state) {
41425f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis        // Verify that command buffers in pool are complete (not in-flight)
4143c8d1e7bb99c01ae0c2824fe7286fb0a1173de589John Zulauf        skip |= checkCommandBuffersInFlight(dev_data, cp_state, "destroy command pool with", VALIDATION_ERROR_24000052);
41445f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis    }
41455f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis    return skip;
41465f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis}
41475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
4148c8d1e7bb99c01ae0c2824fe7286fb0a1173de589John Zulaufstatic void PostCallRecordDestroyCommandPool(layer_data *dev_data, VkCommandPool pool) {
4149c8d1e7bb99c01ae0c2824fe7286fb0a1173de589John Zulauf    COMMAND_POOL_NODE *cp_state = GetCommandPoolNode(dev_data, pool);
4150c8d1e7bb99c01ae0c2824fe7286fb0a1173de589John Zulauf    // Remove cmdpool from cmdpoolmap, after freeing layer data for the command buffers
4151c8d1e7bb99c01ae0c2824fe7286fb0a1173de589John Zulauf    // "When a pool is destroyed, all command buffers allocated from the pool are freed."
4152c8d1e7bb99c01ae0c2824fe7286fb0a1173de589John Zulauf    if (cp_state) {
4153c8d1e7bb99c01ae0c2824fe7286fb0a1173de589John Zulauf        // Create a vector, as FreeCommandBufferStates deletes from cp_state->commandBuffers during iteration.
4154c8d1e7bb99c01ae0c2824fe7286fb0a1173de589John Zulauf        std::vector<VkCommandBuffer> cb_vec{cp_state->commandBuffers.begin(), cp_state->commandBuffers.end()};
4155c8d1e7bb99c01ae0c2824fe7286fb0a1173de589John Zulauf        FreeCommandBufferStates(dev_data, cp_state, static_cast<uint32_t>(cb_vec.size()), cb_vec.data());
4156c8d1e7bb99c01ae0c2824fe7286fb0a1173de589John Zulauf        dev_data->commandPoolMap.erase(pool);
4157a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes    }
41585f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis}
4159e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis
41605f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis// Destroy commandPool along with all of the commandBuffers allocated from that pool
41615f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin EhlisVKAPI_ATTR void VKAPI_CALL DestroyCommandPool(VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks *pAllocator) {
416256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
4163ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
4164c8d1e7bb99c01ae0c2824fe7286fb0a1173de589John Zulauf    bool skip = PreCallValidateDestroyCommandPool(dev_data, commandPool);
41655f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis    if (!skip) {
41665f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis        lock.unlock();
41675f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis        dev_data->dispatch_table.DestroyCommandPool(device, commandPool, pAllocator);
41685f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis        lock.lock();
4169405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        if (commandPool != VK_NULL_HANDLE) {
4170c8d1e7bb99c01ae0c2824fe7286fb0a1173de589John Zulauf            PostCallRecordDestroyCommandPool(dev_data, commandPool);
4171405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        }
41725f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis    }
41735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
41745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
4175bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL ResetCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolResetFlags flags) {
417656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
41773251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
4178400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis
4179ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
41809a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto pPool = GetCommandPoolNode(dev_data, commandPool);
4181315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis    skip |= checkCommandBuffersInFlight(dev_data, pPool, "reset command pool with", VALIDATION_ERROR_32800050);
41821ec6311a8537f4467db08eacbd762ebaa87e70b0Chris Forbes    lock.unlock();
4183a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes
41843251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
41855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
41864a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.ResetCommandPool(device, commandPool, flags);
41875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
41885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Reset all of the CBs allocated from this pool
41895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
41901ec6311a8537f4467db08eacbd762ebaa87e70b0Chris Forbes        lock.lock();
4191a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes        for (auto cmdBuffer : pPool->commandBuffers) {
41927cb00fa300f2563ae3e8eb506bca912c11216953John Zulauf            ResetCommandBufferState(dev_data, cmdBuffer);
41935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
41941ec6311a8537f4467db08eacbd762ebaa87e70b0Chris Forbes        lock.unlock();
41955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
41965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
41975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
41985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
419989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL ResetFences(VkDevice device, uint32_t fenceCount, const VkFence *pFences) {
420056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
42013251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
4202ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
42035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < fenceCount; ++i) {
42049a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto pFence = GetFenceNode(dev_data, pFences[i]);
4205804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt        if (pFence && pFence->scope == kSyncScopeInternal && pFence->state == FENCE_INFLIGHT) {
4206315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis            skip |=
4207315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT,
4208315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(pFences[i]), __LINE__, VALIDATION_ERROR_32e008c6, "DS", "Fence 0x%" PRIx64 " is in use. %s",
4209315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(pFences[i]), validation_error_map[VALIDATION_ERROR_32e008c6]);
42105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
42115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
4212b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
4213090da73358f71ba026e2474a822fecf55267d166Chris Forbes
42143251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
4215090da73358f71ba026e2474a822fecf55267d166Chris Forbes
42164a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.ResetFences(device, fenceCount, pFences);
4217090da73358f71ba026e2474a822fecf55267d166Chris Forbes
4218090da73358f71ba026e2474a822fecf55267d166Chris Forbes    if (result == VK_SUCCESS) {
4219090da73358f71ba026e2474a822fecf55267d166Chris Forbes        lock.lock();
4220090da73358f71ba026e2474a822fecf55267d166Chris Forbes        for (uint32_t i = 0; i < fenceCount; ++i) {
42219a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            auto pFence = GetFenceNode(dev_data, pFences[i]);
4222090da73358f71ba026e2474a822fecf55267d166Chris Forbes            if (pFence) {
4223804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt                if (pFence->scope == kSyncScopeInternal) {
4224804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt                    pFence->state = FENCE_UNSIGNALED;
4225804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt                } else if (pFence->scope == kSyncScopeExternalTemporary) {
4226804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt                    pFence->scope = kSyncScopeInternal;
4227804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt                }
4228090da73358f71ba026e2474a822fecf55267d166Chris Forbes            }
4229090da73358f71ba026e2474a822fecf55267d166Chris Forbes        }
4230090da73358f71ba026e2474a822fecf55267d166Chris Forbes        lock.unlock();
4231090da73358f71ba026e2474a822fecf55267d166Chris Forbes    }
4232090da73358f71ba026e2474a822fecf55267d166Chris Forbes
42335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
42345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
42355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
4236e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis// For given cb_nodes, invalidate them and track object causing invalidation
42370a4087f99558069e9f6a437ff2dbb5a9c1c22ccaTobin Ehlisvoid invalidateCommandBuffers(const layer_data *dev_data, std::unordered_set<GLOBAL_CB_NODE *> const &cb_nodes, VK_OBJECT obj) {
4238e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis    for (auto cb_node : cb_nodes) {
423939c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis        if (cb_node->state == CB_RECORDING) {
424039c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis            log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
42419b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                    HandleToUint64(cb_node->commandBuffer), __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER, "DS",
4242226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis                    "Invalidating a command buffer that's currently being recorded: 0x%p.", cb_node->commandBuffer);
424346daa701a01b92ae19e3ee9e661d677128fe7e6dChris Forbes            cb_node->state = CB_INVALID_INCOMPLETE;
424446daa701a01b92ae19e3ee9e661d677128fe7e6dChris Forbes        }
4245ecf6f4952415c47ebb64999e1a962c4f688ca0f7Chris Forbes        else if (cb_node->state == CB_RECORDED) {
424646daa701a01b92ae19e3ee9e661d677128fe7e6dChris Forbes            cb_node->state = CB_INVALID_COMPLETE;
424739c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis        }
4248e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis        cb_node->broken_bindings.push_back(obj);
4249db365f522319df6446b50584277a3bbfee1c1052Chris Forbes
4250db365f522319df6446b50584277a3bbfee1c1052Chris Forbes        // if secondary, then propagate the invalidation to the primaries that will call us.
4251db365f522319df6446b50584277a3bbfee1c1052Chris Forbes        if (cb_node->createInfo.level == VK_COMMAND_BUFFER_LEVEL_SECONDARY) {
4252db365f522319df6446b50584277a3bbfee1c1052Chris Forbes            invalidateCommandBuffers(dev_data, cb_node->linkedCommandBuffers, obj);
4253db365f522319df6446b50584277a3bbfee1c1052Chris Forbes        }
4254e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis    }
4255e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis}
4256e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis
4257c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlisstatic bool PreCallValidateDestroyFramebuffer(layer_data *dev_data, VkFramebuffer framebuffer,
4258c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis                                              FRAMEBUFFER_STATE **framebuffer_state, VK_OBJECT *obj_struct) {
42599a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    *framebuffer_state = GetFramebufferState(dev_data, framebuffer);
42609b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus    *obj_struct = {HandleToUint64(framebuffer), kVulkanObjectTypeFramebuffer};
4261cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.destroy_framebuffer) return false;
4262728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis    bool skip = false;
4263728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis    if (*framebuffer_state) {
426469ea2c79d7b3f9c987671a10686afac066b275b9Mike Schuchardt        skip |=
426569ea2c79d7b3f9c987671a10686afac066b275b9Mike Schuchardt            ValidateObjectNotInUse(dev_data, *framebuffer_state, *obj_struct, "vkDestroyFrameBuffer", VALIDATION_ERROR_250006f8);
4266728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis    }
4267728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis    return skip;
4268728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis}
4269728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis
4270c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlisstatic void PostCallRecordDestroyFramebuffer(layer_data *dev_data, VkFramebuffer framebuffer, FRAMEBUFFER_STATE *framebuffer_state,
4271728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis                                             VK_OBJECT obj_struct) {
427239c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis    invalidateCommandBuffers(dev_data, framebuffer_state->cb_bindings, obj_struct);
4273728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis    dev_data->frameBufferMap.erase(framebuffer);
4274728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis}
4275728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis
4276bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyFramebuffer(VkDevice device, VkFramebuffer framebuffer, const VkAllocationCallbacks *pAllocator) {
427756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
4278c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis    FRAMEBUFFER_STATE *framebuffer_state = nullptr;
4279728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis    VK_OBJECT obj_struct;
4280ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
4281728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis    bool skip = PreCallValidateDestroyFramebuffer(dev_data, framebuffer, &framebuffer_state, &obj_struct);
4282728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis    if (!skip) {
4283728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis        lock.unlock();
4284728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis        dev_data->dispatch_table.DestroyFramebuffer(device, framebuffer, pAllocator);
4285728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis        lock.lock();
4286405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        if (framebuffer != VK_NULL_HANDLE) {
4287405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour            PostCallRecordDestroyFramebuffer(dev_data, framebuffer, framebuffer_state, obj_struct);
4288405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        }
42895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
42905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
42915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
42920ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlisstatic bool PreCallValidateDestroyRenderPass(layer_data *dev_data, VkRenderPass render_pass, RENDER_PASS_STATE **rp_state,
42930ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis                                             VK_OBJECT *obj_struct) {
42949a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    *rp_state = GetRenderPassState(dev_data, render_pass);
42959b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus    *obj_struct = {HandleToUint64(render_pass), kVulkanObjectTypeRenderPass};
4296cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.destroy_renderpass) return false;
42970ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis    bool skip = false;
42980ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis    if (*rp_state) {
429969ea2c79d7b3f9c987671a10686afac066b275b9Mike Schuchardt        skip |= ValidateObjectNotInUse(dev_data, *rp_state, *obj_struct, "vkDestroyRenderPass", VALIDATION_ERROR_264006d2);
43000ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis    }
43010ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis    return skip;
43020ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis}
43030ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis
43040ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlisstatic void PostCallRecordDestroyRenderPass(layer_data *dev_data, VkRenderPass render_pass, RENDER_PASS_STATE *rp_state,
43050ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis                                            VK_OBJECT obj_struct) {
430639c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis    invalidateCommandBuffers(dev_data, rp_state->cb_bindings, obj_struct);
43070ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis    dev_data->renderPassMap.erase(render_pass);
43080ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis}
43090ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis
4310bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyRenderPass(VkDevice device, VkRenderPass renderPass, const VkAllocationCallbacks *pAllocator) {
431156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
43120ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis    RENDER_PASS_STATE *rp_state = nullptr;
43130ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis    VK_OBJECT obj_struct;
4314ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
43150ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis    bool skip = PreCallValidateDestroyRenderPass(dev_data, renderPass, &rp_state, &obj_struct);
4316a9fbfe0c622e9fa4b56ddd015ed4c3c409020c2eTobin Ehlis    if (!skip) {
4317a9fbfe0c622e9fa4b56ddd015ed4c3c409020c2eTobin Ehlis        lock.unlock();
43184a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.DestroyRenderPass(device, renderPass, pAllocator);
43190ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis        lock.lock();
4320405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        if (renderPass != VK_NULL_HANDLE) {
4321405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour            PostCallRecordDestroyRenderPass(dev_data, renderPass, rp_state, obj_struct);
4322405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        }
4323a9fbfe0c622e9fa4b56ddd015ed4c3c409020c2eTobin Ehlis    }
43245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
43255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
432689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateBuffer(VkDevice device, const VkBufferCreateInfo *pCreateInfo,
432789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                            const VkAllocationCallbacks *pAllocator, VkBuffer *pBuffer) {
432856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
4329ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
43303683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    bool skip = PreCallValidateCreateBuffer(dev_data, pCreateInfo);
43313683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    lock.unlock();
43323683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski
43333683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
43344a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.CreateBuffer(device, pCreateInfo, pAllocator, pBuffer);
43355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
43365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
43373683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski        lock.lock();
43383683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski        PostCallRecordCreateBuffer(dev_data, pCreateInfo, pBuffer);
43393683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski        lock.unlock();
43405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
43415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
43425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
43435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
434489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateBufferView(VkDevice device, const VkBufferViewCreateInfo *pCreateInfo,
434589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                                const VkAllocationCallbacks *pAllocator, VkBufferView *pView) {
434656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
4347ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
43483251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = PreCallValidateCreateBufferView(dev_data, pCreateInfo);
43498c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young    lock.unlock();
43503251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
43514a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.CreateBufferView(device, pCreateInfo, pAllocator, pView);
43525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
43538c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young        lock.lock();
43543683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski        PostCallRecordCreateBufferView(dev_data, pCreateInfo, pView);
43558c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young        lock.unlock();
43565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
43575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
43585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
43595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
43608dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski// Access helper functions for external modules
436157f0da98098689f3624c5503cfe1a4b5fede885aJeremy KniagerVkFormatProperties GetFormatProperties(core_validation::layer_data *device_data, VkFormat format) {
436257f0da98098689f3624c5503cfe1a4b5fede885aJeremy Kniager    VkFormatProperties format_properties;
4363d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski    instance_layer_data *instance_data =
4364d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski        GetLayerDataPtr(get_dispatch_key(device_data->instance_data->instance), instance_layer_data_map);
436557f0da98098689f3624c5503cfe1a4b5fede885aJeremy Kniager    instance_data->dispatch_table.GetPhysicalDeviceFormatProperties(device_data->physical_device, format, &format_properties);
4366d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski    return format_properties;
43678dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski}
43688dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
436957f0da98098689f3624c5503cfe1a4b5fede885aJeremy KniagerVkImageFormatProperties GetImageFormatProperties(core_validation::layer_data *device_data, VkFormat format, VkImageType image_type,
437057f0da98098689f3624c5503cfe1a4b5fede885aJeremy Kniager                                                 VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags) {
437157f0da98098689f3624c5503cfe1a4b5fede885aJeremy Kniager    VkImageFormatProperties image_format_properties;
4372d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski    instance_layer_data *instance_data =
4373d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski        GetLayerDataPtr(get_dispatch_key(device_data->instance_data->instance), instance_layer_data_map);
4374d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski    instance_data->dispatch_table.GetPhysicalDeviceImageFormatProperties(device_data->physical_device, format, image_type, tiling,
437557f0da98098689f3624c5503cfe1a4b5fede885aJeremy Kniager                                                                         usage, flags, &image_format_properties);
4376d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski    return image_format_properties;
43778dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski}
43788dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
43797a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlisconst debug_report_data *GetReportData(const core_validation::layer_data *device_data) { return device_data->report_data; }
43808dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
43818dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinskiconst VkPhysicalDeviceProperties *GetPhysicalDeviceProperties(core_validation::layer_data *device_data) {
43828dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    return &device_data->phys_dev_props;
43838dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski}
43848dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski
43858c59133586421be878d393799b30044497f77727Mark Lobodzinskiconst CHECK_DISABLED *GetDisables(core_validation::layer_data *device_data) { return &device_data->instance_data->disabled; }
43868c59133586421be878d393799b30044497f77727Mark Lobodzinski
43878c59133586421be878d393799b30044497f77727Mark Lobodzinskistd::unordered_map<VkImage, std::unique_ptr<IMAGE_STATE>> *GetImageMap(core_validation::layer_data *device_data) {
43888c59133586421be878d393799b30044497f77727Mark Lobodzinski    return &device_data->imageMap;
43898c59133586421be878d393799b30044497f77727Mark Lobodzinski}
43908c59133586421be878d393799b30044497f77727Mark Lobodzinski
43918c59133586421be878d393799b30044497f77727Mark Lobodzinskistd::unordered_map<VkImage, std::vector<ImageSubresourcePair>> *GetImageSubresourceMap(core_validation::layer_data *device_data) {
43928c59133586421be878d393799b30044497f77727Mark Lobodzinski    return &device_data->imageSubresourceMap;
43938c59133586421be878d393799b30044497f77727Mark Lobodzinski}
43948c59133586421be878d393799b30044497f77727Mark Lobodzinski
43958c59133586421be878d393799b30044497f77727Mark Lobodzinskistd::unordered_map<ImageSubresourcePair, IMAGE_LAYOUT_NODE> *GetImageLayoutMap(layer_data *device_data) {
43968c59133586421be878d393799b30044497f77727Mark Lobodzinski    return &device_data->imageLayoutMap;
43978c59133586421be878d393799b30044497f77727Mark Lobodzinski}
43988c59133586421be878d393799b30044497f77727Mark Lobodzinski
43990db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlisstd::unordered_map<ImageSubresourcePair, IMAGE_LAYOUT_NODE> const *GetImageLayoutMap(layer_data const *device_data) {
44000db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis    return &device_data->imageLayoutMap;
44010db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis}
44020db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis
44033683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinskistd::unordered_map<VkBuffer, std::unique_ptr<BUFFER_STATE>> *GetBufferMap(layer_data *device_data) {
44043683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    return &device_data->bufferMap;
44053683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski}
44063683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski
44073683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinskistd::unordered_map<VkBufferView, std::unique_ptr<BUFFER_VIEW_STATE>> *GetBufferViewMap(layer_data *device_data) {
44083683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski    return &device_data->bufferViewMap;
44093683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski}
44103683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski
44111c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinskistd::unordered_map<VkImageView, std::unique_ptr<IMAGE_VIEW_STATE>> *GetImageViewMap(layer_data *device_data) {
44121c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski    return &device_data->imageViewMap;
44131c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski}
44141c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski
4415d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinskiconst PHYS_DEV_PROPERTIES_NODE *GetPhysDevProperties(const layer_data *device_data) {
44166a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    return &device_data->phys_dev_properties;
44176a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski}
44186a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski
44195f3e7c34de87353f38bbcd79e12de8af4a9e7695Mark Lobodzinskiconst VkPhysicalDeviceFeatures *GetEnabledFeatures(const layer_data *device_data) {
44205f3e7c34de87353f38bbcd79e12de8af4a9e7695Mark Lobodzinski    return &device_data->enabled_features;
44215f3e7c34de87353f38bbcd79e12de8af4a9e7695Mark Lobodzinski}
44225f3e7c34de87353f38bbcd79e12de8af4a9e7695Mark Lobodzinski
4423a149f1a0cb39b48b19822c8cf9ef2426cd2251dfMark Lobodzinskiconst DeviceExtensions *GetDeviceExtensions(const layer_data *device_data) { return &device_data->extensions; }
44240e2296e24065d02615ee87561bbb80af414a1ddfMike Schuchardt
442589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo,
442689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                           const VkAllocationCallbacks *pAllocator, VkImage *pImage) {
44278dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
442856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
44298dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    bool skip = PreCallValidateCreateImage(dev_data, pCreateInfo, pAllocator, pImage);
44308dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    if (!skip) {
44318dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski        result = dev_data->dispatch_table.CreateImage(device, pCreateInfo, pAllocator, pImage);
44328dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski    }
44335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
4434ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes        lock_guard_t lock(global_lock);
4435920311b6aa5614a545cad59521770d0898a75d65Mark Lobodzinski        PostCallRecordCreateImage(dev_data, pCreateInfo, pImage);
44365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
44375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
44385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
44395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
44408c07a094dc9cc4afb6b62181f341c12b9e969041Mark YoungVKAPI_ATTR VkResult VKAPI_CALL CreateImageView(VkDevice device, const VkImageViewCreateInfo *pCreateInfo,
44418c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young                                               const VkAllocationCallbacks *pAllocator, VkImageView *pView) {
444256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
4443ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
4444e3effabf8e97cae8e006477806ceaca62e4f2ce7Tobin Ehlis    bool skip = PreCallValidateCreateImageView(dev_data, pCreateInfo);
44458c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young    lock.unlock();
4446cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
44474a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.CreateImageView(device, pCreateInfo, pAllocator, pView);
44485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
44498c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young        lock.lock();
445079fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis        PostCallRecordCreateImageView(dev_data, pCreateInfo, *pView);
44518c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young        lock.unlock();
44525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
4453bb6624cb996175d8945190886a200e720b3871efChris Forbes
44545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
44555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
44565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
4457bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateFence(VkDevice device, const VkFenceCreateInfo *pCreateInfo,
4458bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                           const VkAllocationCallbacks *pAllocator, VkFence *pFence) {
445956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
44604a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.CreateFence(device, pCreateInfo, pAllocator, pFence);
44615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
4462ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes        lock_guard_t lock(global_lock);
4463a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis        auto &fence_node = dev_data->fenceMap[*pFence];
44648988ad37ea5a054ff2ae3cbe4b767ae6c13cf48bChris Forbes        fence_node.fence = *pFence;
4465a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis        fence_node.createInfo = *pCreateInfo;
4466cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes        fence_node.state = (pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT) ? FENCE_RETIRED : FENCE_UNSIGNALED;
44675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
44685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
44695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
44705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
44715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// TODO handle pipeline caches
447289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreatePipelineCache(VkDevice device, const VkPipelineCacheCreateInfo *pCreateInfo,
447389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                                   const VkAllocationCallbacks *pAllocator, VkPipelineCache *pPipelineCache) {
447456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
44754a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.CreatePipelineCache(device, pCreateInfo, pAllocator, pPipelineCache);
44765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
44775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
44785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
4479bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyPipelineCache(VkDevice device, VkPipelineCache pipelineCache,
4480bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                const VkAllocationCallbacks *pAllocator) {
448156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
44824a0754042cf090e131e9e769d8a3633c228625beChris Forbes    dev_data->dispatch_table.DestroyPipelineCache(device, pipelineCache, pAllocator);
44835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
44845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
4485bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL GetPipelineCacheData(VkDevice device, VkPipelineCache pipelineCache, size_t *pDataSize,
4486bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                    void *pData) {
448756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
44884a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.GetPipelineCacheData(device, pipelineCache, pDataSize, pData);
44895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
44905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
44915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
4492bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL MergePipelineCaches(VkDevice device, VkPipelineCache dstCache, uint32_t srcCacheCount,
4493bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                   const VkPipelineCache *pSrcCaches) {
449456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
44954a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.MergePipelineCaches(device, dstCache, srcCacheCount, pSrcCaches);
44965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
44975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
44985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
4499fe772548f7a48b12772483e8faecc956fb76eb42Chris Forbes// Validation cache:
4500fe772548f7a48b12772483e8faecc956fb76eb42Chris Forbes// CV is the bottommost implementor of this extension. Don't pass calls down.
4501fe772548f7a48b12772483e8faecc956fb76eb42Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateValidationCacheEXT(VkDevice device, const VkValidationCacheCreateInfoEXT *pCreateInfo,
4502f85ac0ee54f3cfbac8bb9bf046de2f502e9b8bffCort Stratton                                                        const VkAllocationCallbacks *pAllocator,
4503f85ac0ee54f3cfbac8bb9bf046de2f502e9b8bffCort Stratton                                                        VkValidationCacheEXT *pValidationCache) {
4504fe772548f7a48b12772483e8faecc956fb76eb42Chris Forbes    *pValidationCache = ValidationCache::Create(pCreateInfo);
4505fe772548f7a48b12772483e8faecc956fb76eb42Chris Forbes    return *pValidationCache ? VK_SUCCESS : VK_ERROR_INITIALIZATION_FAILED;
4506fe772548f7a48b12772483e8faecc956fb76eb42Chris Forbes}
4507fe772548f7a48b12772483e8faecc956fb76eb42Chris Forbes
4508fe772548f7a48b12772483e8faecc956fb76eb42Chris ForbesVKAPI_ATTR void VKAPI_CALL DestroyValidationCacheEXT(VkDevice device, VkValidationCacheEXT validationCache,
4509f85ac0ee54f3cfbac8bb9bf046de2f502e9b8bffCort Stratton                                                     const VkAllocationCallbacks *pAllocator) {
4510fe772548f7a48b12772483e8faecc956fb76eb42Chris Forbes    delete (ValidationCache *)validationCache;
4511fe772548f7a48b12772483e8faecc956fb76eb42Chris Forbes}
4512fe772548f7a48b12772483e8faecc956fb76eb42Chris Forbes
4513fe772548f7a48b12772483e8faecc956fb76eb42Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL GetValidationCacheDataEXT(VkDevice device, VkValidationCacheEXT validationCache, size_t *pDataSize,
4514f85ac0ee54f3cfbac8bb9bf046de2f502e9b8bffCort Stratton                                                         void *pData) {
4515fe772548f7a48b12772483e8faecc956fb76eb42Chris Forbes    size_t inSize = *pDataSize;
4516fe772548f7a48b12772483e8faecc956fb76eb42Chris Forbes    ((ValidationCache *)validationCache)->Write(pDataSize, pData);
4517fe772548f7a48b12772483e8faecc956fb76eb42Chris Forbes    return (pData && *pDataSize != inSize) ? VK_INCOMPLETE : VK_SUCCESS;
4518fe772548f7a48b12772483e8faecc956fb76eb42Chris Forbes}
4519fe772548f7a48b12772483e8faecc956fb76eb42Chris Forbes
4520fe772548f7a48b12772483e8faecc956fb76eb42Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL MergeValidationCachesEXT(VkDevice device, VkValidationCacheEXT dstCache, uint32_t srcCacheCount,
4521b1260c070b19760942d5fddf0d7b1d8872311277Cort Stratton                                                        const VkValidationCacheEXT *pSrcCaches) {
4522b1260c070b19760942d5fddf0d7b1d8872311277Cort Stratton    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
4523b1260c070b19760942d5fddf0d7b1d8872311277Cort Stratton    bool skip = false;
4524fe772548f7a48b12772483e8faecc956fb76eb42Chris Forbes    auto dst = (ValidationCache *)dstCache;
4525b1260c070b19760942d5fddf0d7b1d8872311277Cort Stratton    auto src = (ValidationCache const *const *)pSrcCaches;
4526b1260c070b19760942d5fddf0d7b1d8872311277Cort Stratton    VkResult result = VK_SUCCESS;
4527b1260c070b19760942d5fddf0d7b1d8872311277Cort Stratton    for (uint32_t i = 0; i < srcCacheCount; i++) {
4528b1260c070b19760942d5fddf0d7b1d8872311277Cort Stratton        if (src[i] == dst) {
4529b1260c070b19760942d5fddf0d7b1d8872311277Cort Stratton            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT,
4530b1260c070b19760942d5fddf0d7b1d8872311277Cort Stratton                            0, __LINE__, VALIDATION_ERROR_3e600c00, "DS",
4531b1260c070b19760942d5fddf0d7b1d8872311277Cort Stratton                            "vkMergeValidationCachesEXT: dstCache (0x%" PRIxLEAST64 ") must not appear in pSrcCaches array. %s",
4532b1260c070b19760942d5fddf0d7b1d8872311277Cort Stratton                            HandleToUint64(dstCache), validation_error_map[VALIDATION_ERROR_3e600c00]);
4533b1260c070b19760942d5fddf0d7b1d8872311277Cort Stratton            result = VK_ERROR_VALIDATION_FAILED_EXT;
4534b1260c070b19760942d5fddf0d7b1d8872311277Cort Stratton        }
4535b1260c070b19760942d5fddf0d7b1d8872311277Cort Stratton        if (!skip) {
4536b1260c070b19760942d5fddf0d7b1d8872311277Cort Stratton            dst->Merge(src[i]);
4537b1260c070b19760942d5fddf0d7b1d8872311277Cort Stratton        }
4538b1260c070b19760942d5fddf0d7b1d8872311277Cort Stratton    }
4539fe772548f7a48b12772483e8faecc956fb76eb42Chris Forbes
4540b1260c070b19760942d5fddf0d7b1d8872311277Cort Stratton    return result;
4541fe772548f7a48b12772483e8faecc956fb76eb42Chris Forbes}
4542fe772548f7a48b12772483e8faecc956fb76eb42Chris Forbes
45433d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis// utility function to set collective state for pipeline
45444c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlisvoid set_pipeline_state(PIPELINE_STATE *pPipe) {
45453d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis    // If any attachment used by this pipeline has blendEnable, set top-level blendEnable
45463d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis    if (pPipe->graphicsPipelineCI.pColorBlendState) {
45473d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis        for (size_t i = 0; i < pPipe->attachments.size(); ++i) {
45483d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis            if (VK_TRUE == pPipe->attachments[i].blendEnable) {
45493d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis                if (((pPipe->attachments[i].dstAlphaBlendFactor >= VK_BLEND_FACTOR_CONSTANT_COLOR) &&
45503d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis                     (pPipe->attachments[i].dstAlphaBlendFactor <= VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA)) ||
45513d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis                    ((pPipe->attachments[i].dstColorBlendFactor >= VK_BLEND_FACTOR_CONSTANT_COLOR) &&
45523d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis                     (pPipe->attachments[i].dstColorBlendFactor <= VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA)) ||
45533d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis                    ((pPipe->attachments[i].srcAlphaBlendFactor >= VK_BLEND_FACTOR_CONSTANT_COLOR) &&
45543d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis                     (pPipe->attachments[i].srcAlphaBlendFactor <= VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA)) ||
45553d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis                    ((pPipe->attachments[i].srcColorBlendFactor >= VK_BLEND_FACTOR_CONSTANT_COLOR) &&
45563d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis                     (pPipe->attachments[i].srcColorBlendFactor <= VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA))) {
45573d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis                    pPipe->blendConstantsEnabled = true;
45583d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis                }
45593d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis            }
45603d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis        }
45613d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis    }
45623d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis}
45633d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis
4564daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinskibool validate_dual_src_blend_feature(layer_data *device_data, PIPELINE_STATE *pipe_state) {
4565daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski    bool skip = false;
4566daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski    if (pipe_state->graphicsPipelineCI.pColorBlendState) {
4567daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski        for (size_t i = 0; i < pipe_state->attachments.size(); ++i) {
4568daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski            if (!device_data->enabled_features.dualSrcBlend) {
4569daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski                if ((pipe_state->attachments[i].dstAlphaBlendFactor == VK_BLEND_FACTOR_SRC1_COLOR) ||
4570daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski                    (pipe_state->attachments[i].dstAlphaBlendFactor == VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR) ||
4571daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski                    (pipe_state->attachments[i].dstAlphaBlendFactor == VK_BLEND_FACTOR_SRC1_ALPHA) ||
4572daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski                    (pipe_state->attachments[i].dstAlphaBlendFactor == VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA) ||
4573daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski                    (pipe_state->attachments[i].srcAlphaBlendFactor == VK_BLEND_FACTOR_SRC1_COLOR) ||
4574daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski                    (pipe_state->attachments[i].srcAlphaBlendFactor == VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR) ||
4575daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski                    (pipe_state->attachments[i].srcAlphaBlendFactor == VK_BLEND_FACTOR_SRC1_ALPHA) ||
4576daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski                    (pipe_state->attachments[i].srcAlphaBlendFactor == VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA)) {
4577daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski                    skip |=
4578daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski                        log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
45799b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                HandleToUint64(pipe_state->pipeline), __LINE__, DRAWSTATE_INVALID_FEATURE, "DS",
4580daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski                                "CmdBindPipeline: vkPipeline (0x%" PRIxLEAST64 ") attachment[" PRINTF_SIZE_T_SPECIFIER
4581daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski                                "] has a dual-source blend factor but this device feature is not enabled.",
45829b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                HandleToUint64(pipe_state->pipeline), i);
4583daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski                }
4584daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski            }
4585daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski        }
4586daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski    }
4587daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski    return skip;
4588daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski}
4589daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski
4590bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
4591bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                       const VkGraphicsPipelineCreateInfo *pCreateInfos,
4592bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                       const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines) {
45935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // The order of operations here is a little convoluted but gets the job done
45944c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis    //  1. Pipeline create state is first shadowed into PIPELINE_STATE struct
45955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    //  2. Create state is then validated (which uses flags setup during shadowing)
45965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    //  3. If everything looks good, we'll then create the pipeline and add NODE to pipelineMap
459742486a20f07b16f0c5361cdc00fd789b07b1989aMark Lobodzinski    bool skip = false;
45983d67a6d0f5c42da03d838178741ef10928cd6397Chris Forbes    vector<std::unique_ptr<PIPELINE_STATE>> pipe_state;
45993d67a6d0f5c42da03d838178741ef10928cd6397Chris Forbes    pipe_state.reserve(count);
460056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
46015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
46025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    uint32_t i = 0;
4603ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
46045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
46055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (i = 0; i < count; i++) {
46063d67a6d0f5c42da03d838178741ef10928cd6397Chris Forbes        pipe_state.push_back(std::unique_ptr<PIPELINE_STATE>(new PIPELINE_STATE));
4607cafebcdd40427a0713a3564dc8f39e47edbdb02fTobin Ehlis        pipe_state[i]->initGraphicsPipeline(&pCreateInfos[i], GetRenderPassStateSharedPtr(dev_data, pCreateInfos[i].renderPass));
46083800dc6928d2f26ad0da2a3b5796ee1042f70ec0Mark Lobodzinski        pipe_state[i]->render_pass_ci.initialize(GetRenderPassState(dev_data, pCreateInfos[i].renderPass)->createInfo.ptr());
460942486a20f07b16f0c5361cdc00fd789b07b1989aMark Lobodzinski        pipe_state[i]->pipeline_layout = *getPipelineLayout(dev_data, pCreateInfos[i].layout);
46105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
46114260fe87d0d168d6f4e7d65a648be05ebe1dedb3Chris Forbes
46124260fe87d0d168d6f4e7d65a648be05ebe1dedb3Chris Forbes    for (i = 0; i < count; i++) {
46132f521eee4ccb1c84512ea767880df8f38751c0d4Chris Forbes        skip |= ValidatePipelineLocked(dev_data, pipe_state, i);
46144260fe87d0d168d6f4e7d65a648be05ebe1dedb3Chris Forbes    }
46155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
461629243a95b358b0d96ab15064fb3f9b0c0f64b8e9Chris Forbes    lock.unlock();
461729243a95b358b0d96ab15064fb3f9b0c0f64b8e9Chris Forbes
4618c3e70f769bd4aa0988652050444d57cab4925c16Chris Forbes    for (i = 0; i < count; i++) {
4619c3e70f769bd4aa0988652050444d57cab4925c16Chris Forbes        skip |= ValidatePipelineUnlocked(dev_data, pipe_state, i);
4620c3e70f769bd4aa0988652050444d57cab4925c16Chris Forbes    }
4621c3e70f769bd4aa0988652050444d57cab4925c16Chris Forbes
4622c70226063be6148056ceeccf835175a1fd59f24fChris Forbes    if (skip) {
4623c70226063be6148056ceeccf835175a1fd59f24fChris Forbes        for (i = 0; i < count; i++) {
46241ab616b32d4e5b7d62d4a8c41b0c03ea335ab845Chris Forbes            pPipelines[i] = VK_NULL_HANDLE;
4625c70226063be6148056ceeccf835175a1fd59f24fChris Forbes        }
46267a456d188475c23b566334be45dc0489b2789653Chris Forbes        return VK_ERROR_VALIDATION_FAILED_EXT;
46277a456d188475c23b566334be45dc0489b2789653Chris Forbes    }
46287a456d188475c23b566334be45dc0489b2789653Chris Forbes
4629bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski    auto result =
4630bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        dev_data->dispatch_table.CreateGraphicsPipelines(device, pipelineCache, count, pCreateInfos, pAllocator, pPipelines);
46317a456d188475c23b566334be45dc0489b2789653Chris Forbes    lock.lock();
46327a456d188475c23b566334be45dc0489b2789653Chris Forbes    for (i = 0; i < count; i++) {
46333d67a6d0f5c42da03d838178741ef10928cd6397Chris Forbes        if (pPipelines[i] != VK_NULL_HANDLE) {
463461943a7503bc8594338f3364ef42f1d863486c04Chris Forbes            pipe_state[i]->pipeline = pPipelines[i];
463563cddeb5593a0ead9ecd5f74d05f506b37d7ac66Chris Forbes            dev_data->pipelineMap[pPipelines[i]] = std::move(pipe_state[i]);
463661943a7503bc8594338f3364ef42f1d863486c04Chris Forbes        }
46375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
4638c70226063be6148056ceeccf835175a1fd59f24fChris Forbes
46395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
46405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
46415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
4642bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
4643bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                      const VkComputePipelineCreateInfo *pCreateInfos,
4644bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                      const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines) {
46450108a1af0b7c6949846e9d71d00bbfb322b6f7caChris Forbes    bool skip = false;
46465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
4647e708f7e5c363576bfab5b39135d629ab2ce37167Chris Forbes    vector<std::unique_ptr<PIPELINE_STATE>> pPipeState;
4648e708f7e5c363576bfab5b39135d629ab2ce37167Chris Forbes    pPipeState.reserve(count);
464956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
46505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
46515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    uint32_t i = 0;
4652ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
46535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (i = 0; i < count; i++) {
46545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // Create and initialize internal tracking data structure
4655e708f7e5c363576bfab5b39135d629ab2ce37167Chris Forbes        pPipeState.push_back(unique_ptr<PIPELINE_STATE>(new PIPELINE_STATE));
46564c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis        pPipeState[i]->initComputePipeline(&pCreateInfos[i]);
4657c2a5a36d03bbe52f5854a5884346e4a84115e259Tobin Ehlis        pPipeState[i]->pipeline_layout = *getPipelineLayout(dev_data, pCreateInfos[i].layout);
46585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
46595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // TODO: Add Compute Pipeline Verification
4660e708f7e5c363576bfab5b39135d629ab2ce37167Chris Forbes        skip |= validate_compute_pipeline(dev_data, pPipeState[i].get());
46615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
46625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
46637a456d188475c23b566334be45dc0489b2789653Chris Forbes    if (skip) {
46645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (i = 0; i < count; i++) {
4665fcf67c021fdfcbeb12fb04daa9a69ecd7d376c5cChris Forbes            pPipelines[i] = VK_NULL_HANDLE;
46665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
46675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return VK_ERROR_VALIDATION_FAILED_EXT;
46685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
46697a456d188475c23b566334be45dc0489b2789653Chris Forbes
46707a456d188475c23b566334be45dc0489b2789653Chris Forbes    lock.unlock();
4671bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski    auto result =
4672bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        dev_data->dispatch_table.CreateComputePipelines(device, pipelineCache, count, pCreateInfos, pAllocator, pPipelines);
46737a456d188475c23b566334be45dc0489b2789653Chris Forbes    lock.lock();
46747a456d188475c23b566334be45dc0489b2789653Chris Forbes    for (i = 0; i < count; i++) {
4675e708f7e5c363576bfab5b39135d629ab2ce37167Chris Forbes        if (pPipelines[i] != VK_NULL_HANDLE) {
4676fcf67c021fdfcbeb12fb04daa9a69ecd7d376c5cChris Forbes            pPipeState[i]->pipeline = pPipelines[i];
467763cddeb5593a0ead9ecd5f74d05f506b37d7ac66Chris Forbes            dev_data->pipelineMap[pPipelines[i]] = std::move(pPipeState[i]);
4678fcf67c021fdfcbeb12fb04daa9a69ecd7d376c5cChris Forbes        }
46797a456d188475c23b566334be45dc0489b2789653Chris Forbes    }
46807a456d188475c23b566334be45dc0489b2789653Chris Forbes
46815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
46825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
46835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
468489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateSampler(VkDevice device, const VkSamplerCreateInfo *pCreateInfo,
468589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                             const VkAllocationCallbacks *pAllocator, VkSampler *pSampler) {
468656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
46874a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.CreateSampler(device, pCreateInfo, pAllocator, pSampler);
46885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
4689ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes        lock_guard_t lock(global_lock);
4690d31a44af6da568692a73201825459689c9431867Tobin Ehlis        dev_data->samplerMap[*pSampler] = unique_ptr<SAMPLER_STATE>(new SAMPLER_STATE(pSampler, pCreateInfo));
46915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
46925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
46935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
46945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
46950c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlisstatic bool PreCallValidateCreateDescriptorSetLayout(layer_data *dev_data, const VkDescriptorSetLayoutCreateInfo *create_info) {
4696cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.create_descriptor_set_layout) return false;
46970c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis    return cvdescriptorset::DescriptorSetLayout::ValidateCreateInfo(dev_data->report_data, create_info);
46980c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis}
46990c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis
47000c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlisstatic void PostCallRecordCreateDescriptorSetLayout(layer_data *dev_data, const VkDescriptorSetLayoutCreateInfo *create_info,
47010c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis                                                    VkDescriptorSetLayout set_layout) {
47027e180d382f501c7c04408bda1f5fe79317736a4fTobin Ehlis    dev_data->descriptorSetLayoutMap[set_layout] = std::make_shared<cvdescriptorset::DescriptorSetLayout>(create_info, set_layout);
47030c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis}
47040c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis
4705bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateDescriptorSetLayout(VkDevice device, const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
4706bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                         const VkAllocationCallbacks *pAllocator,
4707bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                         VkDescriptorSetLayout *pSetLayout) {
470856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
47090c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
4710ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
47110c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis    bool skip = PreCallValidateCreateDescriptorSetLayout(dev_data, pCreateInfo);
47120c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis    if (!skip) {
47130c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis        lock.unlock();
47140c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis        result = dev_data->dispatch_table.CreateDescriptorSetLayout(device, pCreateInfo, pAllocator, pSetLayout);
47150c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis        if (VK_SUCCESS == result) {
47160c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis            lock.lock();
47170c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis            PostCallRecordCreateDescriptorSetLayout(dev_data, pCreateInfo, *pSetLayout);
47180c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis        }
47195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
47205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
47215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
47225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
47239e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz// Used by CreatePipelineLayout and CmdPushConstants.
47249e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz// Note that the index argument is optional and only used by CreatePipelineLayout.
47259e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultzstatic bool validatePushConstantRange(const layer_data *dev_data, const uint32_t offset, const uint32_t size,
47269e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz                                      const char *caller_name, uint32_t index = 0) {
4727cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.push_constant_range) return false;
47289e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz    uint32_t const maxPushConstantsSize = dev_data->phys_dev_properties.properties.limits.maxPushConstantsSize;
47293251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
47309e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz    // Check that offset + size don't exceed the max.
47319e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz    // Prevent arithetic overflow here by avoiding addition and testing in this order.
47329e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz    if ((offset >= maxPushConstantsSize) || (size > maxPushConstantsSize - offset)) {
47339e24d8153ab63bc3ac08b5a1517c203930b5de91Karl 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.
47349e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        if (0 == strcmp(caller_name, "vkCreatePipelineLayout()")) {
4735e420dd92dcfc04f279e98796a49ee26b2c3ddafeTobin Ehlis            if (offset >= maxPushConstantsSize) {
47363251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
4737315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                __LINE__, VALIDATION_ERROR_11a0024c, "DS",
47383251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "%s call has push constants index %u with offset %u that "
47393251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "exceeds this device's maxPushConstantSize of %u. %s",
4740315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                caller_name, index, offset, maxPushConstantsSize, validation_error_map[VALIDATION_ERROR_11a0024c]);
4741e420dd92dcfc04f279e98796a49ee26b2c3ddafeTobin Ehlis            }
4742e420dd92dcfc04f279e98796a49ee26b2c3ddafeTobin Ehlis            if (size > maxPushConstantsSize - offset) {
4743315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
4744315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                __LINE__, VALIDATION_ERROR_11a00254, "DS",
4745315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                "%s call has push constants index %u with offset %u and size %u that "
4746315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                "exceeds this device's maxPushConstantSize of %u. %s",
4747315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                caller_name, index, offset, size, maxPushConstantsSize,
4748315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                validation_error_map[VALIDATION_ERROR_11a00254]);
4749e420dd92dcfc04f279e98796a49ee26b2c3ddafeTobin Ehlis            }
47509e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        } else if (0 == strcmp(caller_name, "vkCmdPushConstants()")) {
47514527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton            if (offset >= maxPushConstantsSize) {
47523251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
4753315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                __LINE__, VALIDATION_ERROR_1bc002e4, "DS",
47543251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "%s call has push constants index %u with offset %u that "
47553251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "exceeds this device's maxPushConstantSize of %u. %s",
4756315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                caller_name, index, offset, maxPushConstantsSize, validation_error_map[VALIDATION_ERROR_1bc002e4]);
47574527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton            }
47584527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton            if (size > maxPushConstantsSize - offset) {
4759315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
4760315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                __LINE__, VALIDATION_ERROR_1bc002e6, "DS",
4761315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                "%s call has push constants index %u with offset %u and size %u that "
4762315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                "exceeds this device's maxPushConstantSize of %u. %s",
4763315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                caller_name, index, offset, size, maxPushConstantsSize,
4764315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                validation_error_map[VALIDATION_ERROR_1bc002e6]);
47654527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton            }
47669e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        } else {
47673251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
47683251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            __LINE__, DRAWSTATE_INTERNAL_ERROR, "DS", "%s caller not supported.", caller_name);
47699e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        }
47709e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz    }
47719e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz    // size needs to be non-zero and a multiple of 4.
47729e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz    if ((size == 0) || ((size & 0x3) != 0)) {
47739e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        if (0 == strcmp(caller_name, "vkCreatePipelineLayout()")) {
4774891f13be101e95697e5af9503f06da38b0c48f79Tobin Ehlis            if (size == 0) {
47753251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
4776315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                __LINE__, VALIDATION_ERROR_11a00250, "DS",
47773251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "%s call has push constants index %u with "
47783251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "size %u. Size must be greater than zero. %s",
4779315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                caller_name, index, size, validation_error_map[VALIDATION_ERROR_11a00250]);
4780891f13be101e95697e5af9503f06da38b0c48f79Tobin Ehlis            }
4781891f13be101e95697e5af9503f06da38b0c48f79Tobin Ehlis            if (size & 0x3) {
47823251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
4783315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                __LINE__, VALIDATION_ERROR_11a00252, "DS",
47843251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "%s call has push constants index %u with "
47853251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "size %u. Size must be a multiple of 4. %s",
4786315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                caller_name, index, size, validation_error_map[VALIDATION_ERROR_11a00252]);
4787891f13be101e95697e5af9503f06da38b0c48f79Tobin Ehlis            }
47889e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        } else if (0 == strcmp(caller_name, "vkCmdPushConstants()")) {
47894527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton            if (size == 0) {
47903251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
4791315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                __LINE__, VALIDATION_ERROR_1bc2c21b, "DS",
47923251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "%s call has push constants index %u with "
47933251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "size %u. Size must be greater than zero. %s",
4794315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                caller_name, index, size, validation_error_map[VALIDATION_ERROR_1bc2c21b]);
47954527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton            }
47964527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton            if (size & 0x3) {
47973251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
4798315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                __LINE__, VALIDATION_ERROR_1bc002e2, "DS",
47993251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "%s call has push constants index %u with "
48003251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "size %u. Size must be a multiple of 4. %s",
4801315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                caller_name, index, size, validation_error_map[VALIDATION_ERROR_1bc002e2]);
48024527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton            }
48039e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        } else {
48043251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
48053251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            __LINE__, DRAWSTATE_INTERNAL_ERROR, "DS", "%s caller not supported.", caller_name);
48069e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        }
48079e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz    }
48089e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz    // offset needs to be a multiple of 4.
48099e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz    if ((offset & 0x3) != 0) {
48109e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        if (0 == strcmp(caller_name, "vkCreatePipelineLayout()")) {
48113251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
4812315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            __LINE__, VALIDATION_ERROR_11a0024e, "DS",
48133251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "%s call has push constants index %u with "
48143251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "offset %u. Offset must be a multiple of 4. %s",
4815315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            caller_name, index, offset, validation_error_map[VALIDATION_ERROR_11a0024e]);
48169e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        } else if (0 == strcmp(caller_name, "vkCmdPushConstants()")) {
48173251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
4818315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            __LINE__, VALIDATION_ERROR_1bc002e0, "DS",
48193251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "%s call has push constants with "
48203251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "offset %u. Offset must be a multiple of 4. %s",
4821315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            caller_name, offset, validation_error_map[VALIDATION_ERROR_1bc002e0]);
48229e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        } else {
48233251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
48243251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            __LINE__, DRAWSTATE_INTERNAL_ERROR, "DS", "%s caller not supported.", caller_name);
48259e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        }
48265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
48273251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
48285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
48295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
4830bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo,
483189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                                    const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout) {
48323251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
483356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
4834bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz    // TODO : Add checks for VALIDATION_ERRORS 865-870
48359e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz    // Push Constant Range checks
483607a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz    uint32_t i, j;
48375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (i = 0; i < pCreateInfo->pushConstantRangeCount; ++i) {
48383251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= validatePushConstantRange(dev_data, pCreateInfo->pPushConstantRanges[i].offset,
48393251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                          pCreateInfo->pPushConstantRanges[i].size, "vkCreatePipelineLayout()", i);
48409e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        if (0 == pCreateInfo->pPushConstantRanges[i].stageFlags) {
48413251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
4842315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            __LINE__, VALIDATION_ERROR_11a2dc03, "DS", "vkCreatePipelineLayout() call has no stageFlags set. %s",
4843315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            validation_error_map[VALIDATION_ERROR_11a2dc03]);
48449e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        }
48459e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz    }
48463251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
484707a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz
4848bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl 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.
484907a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz    for (i = 0; i < pCreateInfo->pushConstantRangeCount; ++i) {
485007a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz        for (j = i + 1; j < pCreateInfo->pushConstantRangeCount; ++j) {
4851bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz            if (0 != (pCreateInfo->pPushConstantRanges[i].stageFlags & pCreateInfo->pPushConstantRanges[j].stageFlags)) {
48523251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
4853315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                __LINE__, VALIDATION_ERROR_0fe00248, "DS",
48543251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "vkCreatePipelineLayout() Duplicate stage flags found in ranges %d and %d. %s", i, j,
4855315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                validation_error_map[VALIDATION_ERROR_0fe00248]);
48569e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz            }
48575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
48585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
4859f73b2046273413ea1338dd714d67c39f8e0fa09eChris Forbes
486054aae8da345cdc9b9db8ac81e3e03075db79cf9fJózef Kucia    std::vector<std::shared_ptr<cvdescriptorset::DescriptorSetLayout const>> set_layouts(pCreateInfo->setLayoutCount, nullptr);
486154aae8da345cdc9b9db8ac81e3e03075db79cf9fJózef Kucia    unique_lock_t lock(global_lock);
486254aae8da345cdc9b9db8ac81e3e03075db79cf9fJózef Kucia    unsigned int push_descriptor_set_count = 0;
486354aae8da345cdc9b9db8ac81e3e03075db79cf9fJózef Kucia    for (i = 0; i < pCreateInfo->setLayoutCount; ++i) {
486454aae8da345cdc9b9db8ac81e3e03075db79cf9fJózef Kucia        set_layouts[i] = GetDescriptorSetLayout(dev_data, pCreateInfo->pSetLayouts[i]);
486554aae8da345cdc9b9db8ac81e3e03075db79cf9fJózef Kucia        if (set_layouts[i]->IsPushDescriptor()) ++push_descriptor_set_count;
486654aae8da345cdc9b9db8ac81e3e03075db79cf9fJózef Kucia    }
486754aae8da345cdc9b9db8ac81e3e03075db79cf9fJózef Kucia    lock.unlock();
486854aae8da345cdc9b9db8ac81e3e03075db79cf9fJózef Kucia    if (push_descriptor_set_count > 1) {
486954aae8da345cdc9b9db8ac81e3e03075db79cf9fJózef Kucia        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
487054aae8da345cdc9b9db8ac81e3e03075db79cf9fJózef Kucia                        __LINE__, VALIDATION_ERROR_0fe0024a, "DS",
487154aae8da345cdc9b9db8ac81e3e03075db79cf9fJózef Kucia                        "vkCreatePipelineLayout() Multiple push descriptor sets found. %s",
487254aae8da345cdc9b9db8ac81e3e03075db79cf9fJózef Kucia                        validation_error_map[VALIDATION_ERROR_0fe0024a]);
487354aae8da345cdc9b9db8ac81e3e03075db79cf9fJózef Kucia    }
487454aae8da345cdc9b9db8ac81e3e03075db79cf9fJózef Kucia    if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
487554aae8da345cdc9b9db8ac81e3e03075db79cf9fJózef Kucia
48764a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.CreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
48775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
487854aae8da345cdc9b9db8ac81e3e03075db79cf9fJózef Kucia        lock.lock();
48795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        PIPELINE_LAYOUT_NODE &plNode = dev_data->pipelineLayoutMap[*pPipelineLayout];
488069b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis        plNode.layout = *pPipelineLayout;
4881416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis        plNode.set_layouts.resize(pCreateInfo->setLayoutCount);
488254aae8da345cdc9b9db8ac81e3e03075db79cf9fJózef Kucia        plNode.set_layouts.swap(set_layouts);
4883416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis        plNode.push_constant_ranges.resize(pCreateInfo->pushConstantRangeCount);
48845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (i = 0; i < pCreateInfo->pushConstantRangeCount; ++i) {
4885416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis            plNode.push_constant_ranges[i] = pCreateInfo->pPushConstantRanges[i];
48865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
488754aae8da345cdc9b9db8ac81e3e03075db79cf9fJózef Kucia        lock.unlock();
48885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
48895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
48905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
48915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
4892bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateDescriptorPool(VkDevice device, const VkDescriptorPoolCreateInfo *pCreateInfo,
4893bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                    const VkAllocationCallbacks *pAllocator, VkDescriptorPool *pDescriptorPool) {
489456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
48954a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.CreateDescriptorPool(device, pCreateInfo, pAllocator, pDescriptorPool);
48965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
4897a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis        DESCRIPTOR_POOL_STATE *pNewNode = new DESCRIPTOR_POOL_STATE(*pDescriptorPool, pCreateInfo);
48985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (NULL == pNewNode) {
48995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT,
49009b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        HandleToUint64(*pDescriptorPool), __LINE__, DRAWSTATE_OUT_OF_MEMORY, "DS",
4901a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis                        "Out of memory while attempting to allocate DESCRIPTOR_POOL_STATE in vkCreateDescriptorPool()"))
49025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                return VK_ERROR_VALIDATION_FAILED_EXT;
49035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else {
4904ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes            lock_guard_t lock(global_lock);
49055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            dev_data->descriptorPoolMap[*pDescriptorPool] = pNewNode;
49065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
49075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    } else {
49085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // Need to do anything if pool create fails?
49095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
49105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
49115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
49125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
4913bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL ResetDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool,
4914bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                   VkDescriptorPoolResetFlags flags) {
4915315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis    // TODO : Add checks for VALIDATION_ERROR_32a00272
491656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
49174a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.ResetDescriptorPool(device, descriptorPool, flags);
49185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
4919ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes        lock_guard_t lock(global_lock);
49205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        clearDescriptorPool(dev_data, device, descriptorPool, flags);
49215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
49225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
49235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
49242c4e180a4442f968b44f3d5136f7ffda706f6428Chris Forbes// Ensure the pool contains enough descriptors and descriptor sets to satisfy
4925789832b514862c7a7b5b847eeb8e7cacb733b77bTobin Ehlis// an allocation request. Fills common_data with the total number of descriptors of each type required,
4926789832b514862c7a7b5b847eeb8e7cacb733b77bTobin Ehlis// as well as DescriptorSetLayout ptrs used for later update.
49277f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlisstatic bool PreCallValidateAllocateDescriptorSets(layer_data *dev_data, const VkDescriptorSetAllocateInfo *pAllocateInfo,
49287f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlis                                                  cvdescriptorset::AllocateDescriptorSetsData *common_data) {
49297a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis    // Always update common data
49307a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis    cvdescriptorset::UpdateAllocateDescriptorSetsData(dev_data, pAllocateInfo, common_data);
4931cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.allocate_descriptor_sets) return false;
49327e73e5c6b3020b96a821985f73012f2af0f1b992Tobin Ehlis    // All state checks for AllocateDescriptorSets is done in single function
49337a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis    return cvdescriptorset::ValidateAllocateDescriptorSets(dev_data, pAllocateInfo, common_data);
49347e73e5c6b3020b96a821985f73012f2af0f1b992Tobin Ehlis}
49357e73e5c6b3020b96a821985f73012f2af0f1b992Tobin Ehlis// Allocation state was good and call down chain was made so update state based on allocating descriptor sets
49367e73e5c6b3020b96a821985f73012f2af0f1b992Tobin Ehlisstatic void PostCallRecordAllocateDescriptorSets(layer_data *dev_data, const VkDescriptorSetAllocateInfo *pAllocateInfo,
49377f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlis                                                 VkDescriptorSet *pDescriptorSets,
49387f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlis                                                 const cvdescriptorset::AllocateDescriptorSetsData *common_data) {
49397e73e5c6b3020b96a821985f73012f2af0f1b992Tobin Ehlis    // All the updates are contained in a single cvdescriptorset function
49402c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis    cvdescriptorset::PerformAllocateDescriptorSets(pAllocateInfo, pDescriptorSets, common_data, &dev_data->descriptorPoolMap,
4941b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis                                                   &dev_data->setMap, dev_data);
49422c4e180a4442f968b44f3d5136f7ffda706f6428Chris Forbes}
49432c4e180a4442f968b44f3d5136f7ffda706f6428Chris Forbes
4944827e8708bfc431aa792cba005ebf9f1fe35cc7e3Mark Lobodzinski// TODO: PostCallRecord routine is dependent on data generated in PreCallValidate -- needs to be moved out
4945bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL AllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo *pAllocateInfo,
4946bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                      VkDescriptorSet *pDescriptorSets) {
494756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
4948ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
49497f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlis    cvdescriptorset::AllocateDescriptorSetsData common_data(pAllocateInfo->descriptorSetCount);
49503251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = PreCallValidateAllocateDescriptorSets(dev_data, pAllocateInfo, &common_data);
4951b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
4952d173e0daab123373ce75105f2a908f6ae7cef6abChris Forbes
49533251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
4954d173e0daab123373ce75105f2a908f6ae7cef6abChris Forbes
49554a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.AllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
49566511ce241f7f210211e0c0e882f3c14889071f4dChris Forbes
49575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
4958b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.lock();
49597f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlis        PostCallRecordAllocateDescriptorSets(dev_data, pAllocateInfo, pDescriptorSets, &common_data);
4960b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.unlock();
49615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
49625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
49635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
4964cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis// Verify state before freeing DescriptorSets
4965cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlisstatic bool PreCallValidateFreeDescriptorSets(const layer_data *dev_data, VkDescriptorPool pool, uint32_t count,
4966cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis                                              const VkDescriptorSet *descriptor_sets) {
4967cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.free_descriptor_sets) return false;
49683251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
4969cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis    // First make sure sets being destroyed are not currently in-use
4970405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour    for (uint32_t i = 0; i < count; ++i) {
4971405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        if (descriptor_sets[i] != VK_NULL_HANDLE) {
49723251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= validateIdleDescriptorSet(dev_data, descriptor_sets[i], "vkFreeDescriptorSets");
4973405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        }
4974405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour    }
4975cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis
49769a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    DESCRIPTOR_POOL_STATE *pool_state = GetDescriptorPoolState(dev_data, pool);
4977a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis    if (pool_state && !(VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT & pool_state->createInfo.flags)) {
4978cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis        // Can't Free from a NON_FREE pool
49793251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT,
4980315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(pool), __LINE__, VALIDATION_ERROR_28600270, "DS",
49813251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "It is invalid to call vkFreeDescriptorSets() with a pool created without setting "
49823251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT. %s",
4983315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_28600270]);
4984cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis    }
49853251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
4986cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis}
4987cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis// Sets have been removed from the pool so update underlying state
4988cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlisstatic void PostCallRecordFreeDescriptorSets(layer_data *dev_data, VkDescriptorPool pool, uint32_t count,
4989cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis                                             const VkDescriptorSet *descriptor_sets) {
49909a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    DESCRIPTOR_POOL_STATE *pool_state = GetDescriptorPoolState(dev_data, pool);
4991cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis    // Update available descriptor sets in pool
4992cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis    pool_state->availableSets += count;
4993cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis
4994cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis    // For each freed descriptor add its resources back into the pool as available and remove from pool and setMap
4995cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis    for (uint32_t i = 0; i < count; ++i) {
4996405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        if (descriptor_sets[i] != VK_NULL_HANDLE) {
4997405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour            auto descriptor_set = dev_data->setMap[descriptor_sets[i]];
4998405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour            uint32_t type_index = 0, descriptor_count = 0;
4999405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour            for (uint32_t j = 0; j < descriptor_set->GetBindingCount(); ++j) {
5000405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour                type_index = static_cast<uint32_t>(descriptor_set->GetTypeFromIndex(j));
5001405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour                descriptor_count = descriptor_set->GetDescriptorCountFromIndex(j);
5002405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour                pool_state->availableDescriptorTypeCount[type_index] += descriptor_count;
5003405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour            }
5004405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour            freeDescriptorSet(dev_data, descriptor_set);
5005405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour            pool_state->sets.erase(descriptor_set);
5006405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour        }
5007cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis    }
5008cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis}
50095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5010bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL FreeDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool, uint32_t count,
5011bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                  const VkDescriptorSet *pDescriptorSets) {
501256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
50135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Make sure that no sets being destroyed are in-flight
5014ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
50153251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = PreCallValidateFreeDescriptorSets(dev_data, descriptorPool, count, pDescriptorSets);
5016b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
5017e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis
50183251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
50194a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.FreeDescriptorSets(device, descriptorPool, count, pDescriptorSets);
50205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
5021b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.lock();
5022cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis        PostCallRecordFreeDescriptorSets(dev_data, descriptorPool, count, pDescriptorSets);
5023b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.unlock();
50245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
50255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
50265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
50276b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis// TODO : This is a Proof-of-concept for core validation architecture
50286b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis//  Really we'll want to break out these functions to separate files but
50296b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis//  keeping it all together here to prove out design
50306b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis// PreCallValidate* handles validating all of the state prior to calling down chain to UpdateDescriptorSets()
50316b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlisstatic bool PreCallValidateUpdateDescriptorSets(layer_data *dev_data, uint32_t descriptorWriteCount,
50326b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis                                                const VkWriteDescriptorSet *pDescriptorWrites, uint32_t descriptorCopyCount,
50336b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis                                                const VkCopyDescriptorSet *pDescriptorCopies) {
5034cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (dev_data->instance_data->disabled.update_descriptor_sets) return false;
50356b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis    // First thing to do is perform map look-ups.
50366b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis    // NOTE : UpdateDescriptorSets is somewhat unique in that it's operating on a number of DescriptorSets
50376b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis    //  so we can't just do a single map look-up up-front, but do them individually in functions below
50386b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis
50396b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis    // Now make call(s) that validate state, but don't perform state updates in this function
50406b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis    // Note, here DescriptorSets is unique in that we don't yet have an instance. Using a helper function in the
50416b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis    //  namespace which will parse params and make calls into specific class instances
5042104ab082916e41467ef60baaab7a5a8b2e02c59cTobin Ehlis    return cvdescriptorset::ValidateUpdateDescriptorSets(dev_data->report_data, dev_data, descriptorWriteCount, pDescriptorWrites,
5043104ab082916e41467ef60baaab7a5a8b2e02c59cTobin Ehlis                                                         descriptorCopyCount, pDescriptorCopies);
50446b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis}
50456b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis// PostCallRecord* handles recording state updates following call down chain to UpdateDescriptorSets()
50460c9526fb9fbc2d95ebda8902e1de9d9007ba4e9eTobin Ehlisstatic void PreCallRecordUpdateDescriptorSets(layer_data *dev_data, uint32_t descriptorWriteCount,
50470c9526fb9fbc2d95ebda8902e1de9d9007ba4e9eTobin Ehlis                                              const VkWriteDescriptorSet *pDescriptorWrites, uint32_t descriptorCopyCount,
50480c9526fb9fbc2d95ebda8902e1de9d9007ba4e9eTobin Ehlis                                              const VkCopyDescriptorSet *pDescriptorCopies) {
5049104ab082916e41467ef60baaab7a5a8b2e02c59cTobin Ehlis    cvdescriptorset::PerformUpdateDescriptorSets(dev_data, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount,
50506b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis                                                 pDescriptorCopies);
50516b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis}
50525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5053bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL UpdateDescriptorSets(VkDevice device, uint32_t descriptorWriteCount,
5054bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                const VkWriteDescriptorSet *pDescriptorWrites, uint32_t descriptorCopyCount,
5055bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                const VkCopyDescriptorSet *pDescriptorCopies) {
50566b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis    // Only map look-up at top level is for device-level layer_data
505756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
5058ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
50593251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = PreCallValidateUpdateDescriptorSets(dev_data, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount,
50603251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                                    pDescriptorCopies);
50613251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (!skip) {
50620c9526fb9fbc2d95ebda8902e1de9d9007ba4e9eTobin Ehlis        // Since UpdateDescriptorSets() is void, nothing to check prior to updating state & we can update before call down chain
50630c9526fb9fbc2d95ebda8902e1de9d9007ba4e9eTobin Ehlis        PreCallRecordUpdateDescriptorSets(dev_data, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount,
50640c9526fb9fbc2d95ebda8902e1de9d9007ba4e9eTobin Ehlis                                          pDescriptorCopies);
50650c9526fb9fbc2d95ebda8902e1de9d9007ba4e9eTobin Ehlis        lock.unlock();
50664a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.UpdateDescriptorSets(device, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount,
50674a0754042cf090e131e9e769d8a3633c228625beChris Forbes                                                      pDescriptorCopies);
50685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
50695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
50705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5071bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL AllocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo *pCreateInfo,
5072bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                      VkCommandBuffer *pCommandBuffer) {
507356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
50744a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.AllocateCommandBuffers(device, pCreateInfo, pCommandBuffer);
50755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
5076ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes        unique_lock_t lock(global_lock);
50779a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto pPool = GetCommandPoolNode(dev_data, pCreateInfo->commandPool);
5078cd9a648074f67a1d44c15a056b90fc66da8ead17Chris Forbes
5079cd9a648074f67a1d44c15a056b90fc66da8ead17Chris Forbes        if (pPool) {
508072d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis            for (uint32_t i = 0; i < pCreateInfo->commandBufferCount; i++) {
50815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                // Add command buffer to its commandPool map
5082c8d1e7bb99c01ae0c2824fe7286fb0a1173de589John Zulauf                pPool->commandBuffers.insert(pCommandBuffer[i]);
50835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                GLOBAL_CB_NODE *pCB = new GLOBAL_CB_NODE;
50845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                // Add command buffer to map
50855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                dev_data->commandBufferMap[pCommandBuffer[i]] = pCB;
50867cb00fa300f2563ae3e8eb506bca912c11216953John Zulauf                ResetCommandBufferState(dev_data, pCommandBuffer[i]);
50875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                pCB->createInfo = *pCreateInfo;
50885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                pCB->device = device;
50895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
50905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
5091b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.unlock();
50925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
50935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
50945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
50955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5096883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis// Add bindings between the given cmd buffer & framebuffer and the framebuffer's children
5097c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlisstatic void AddFramebufferBinding(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, FRAMEBUFFER_STATE *fb_state) {
50989b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus    addCommandBufferBinding(&fb_state->cb_bindings, {HandleToUint64(fb_state->framebuffer), kVulkanObjectTypeFramebuffer},
50990245b74a083d2cb3b083571deb0fe13b4ab428a4Tobin Ehlis                            cb_state);
5100883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis    for (auto attachment : fb_state->attachments) {
5101883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis        auto view_state = attachment.view_state;
5102883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis        if (view_state) {
510303ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis            AddCommandBufferBindingImageView(dev_data, cb_state, view_state);
5104883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis        }
5105883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis    }
5106883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis}
5107883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis
5108bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL BeginCommandBuffer(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo *pBeginInfo) {
51093251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
511056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
5111ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
51125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Validate command buffer level
51139a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *cb_node = GetCBNode(dev_data, commandBuffer);
5114f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis    if (cb_node) {
51155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // This implicitly resets the Cmd Buffer so make sure any fence is done and then clear memory references
5116a7fef8833e0b4e1e4c7ea20ab56da451a6856c0cChris Forbes        if (cb_node->in_use.load()) {
51173251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
5118315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_16e00062, "MEM",
511959ae0ccadec962d9ca2cce7584fad6c57c1a4458Tobin Ehlis                            "Calling vkBeginCommandBuffer() on active command buffer %p before it has completed. "
51203251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "You must check command buffer fence before this call. %s",
5121315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            commandBuffer, validation_error_map[VALIDATION_ERROR_16e00062]);
51225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
5123f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis        clear_cmd_buf_and_mem_references(dev_data, cb_node);
5124f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis        if (cb_node->createInfo.level != VK_COMMAND_BUFFER_LEVEL_PRIMARY) {
51255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            // Secondary Command Buffer
51265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            const VkCommandBufferInheritanceInfo *pInfo = pBeginInfo->pInheritanceInfo;
51275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (!pInfo) {
51283251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |=
51295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
5130315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_16e00066, "DS",
5131bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                            "vkBeginCommandBuffer(): Secondary Command Buffer (0x%p) must have inheritance info. %s", commandBuffer,
5132315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            validation_error_map[VALIDATION_ERROR_16e00066]);
51335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            } else {
51345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                if (pBeginInfo->flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT) {
51352c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis                    assert(pInfo->renderPass);
51362c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis                    string errorString = "";
51379a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                    auto framebuffer = GetFramebufferState(dev_data, pInfo->framebuffer);
51382c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis                    if (framebuffer) {
5139eacc703e5d08f497f9191991669e99d7330d5c3aTobin Ehlis                        if (framebuffer->createInfo.renderPass != pInfo->renderPass) {
51402c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis                            // renderPass that framebuffer was created with must be compatible with local renderPass
5141eacc703e5d08f497f9191991669e99d7330d5c3aTobin Ehlis                            skip |=
5142ba9be0cec36d930fc0d5a0cbfbc00b0df49b08e4Tobin Ehlis                                validateRenderPassCompatibility(dev_data, "framebuffer", framebuffer->rp_state.get(),
5143ba9be0cec36d930fc0d5a0cbfbc00b0df49b08e4Tobin Ehlis                                                                "command buffer", GetRenderPassState(dev_data, pInfo->renderPass),
5144eacc703e5d08f497f9191991669e99d7330d5c3aTobin Ehlis                                                                "vkBeginCommandBuffer()", VALIDATION_ERROR_0280006e);
51455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        }
51462c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis                        // Connect this framebuffer and its children to this cmdBuffer
51472c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis                        AddFramebufferBinding(dev_data, cb_node, framebuffer);
51485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    }
51495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
51504527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton                if ((pInfo->occlusionQueryEnable == VK_FALSE || dev_data->enabled_features.occlusionQueryPrecise == VK_FALSE) &&
51515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    (pInfo->queryFlags & VK_QUERY_CONTROL_PRECISE_BIT)) {
51523251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
51539b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                    VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, HandleToUint64(commandBuffer), __LINE__,
5154315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    VALIDATION_ERROR_16e00068, "DS",
51553251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    "vkBeginCommandBuffer(): Secondary Command Buffer (0x%p) must not have "
51563251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    "VK_QUERY_CONTROL_PRECISE_BIT if occulusionQuery is disabled or the device does not "
51573251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    "support precise occlusion queries. %s",
5158315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    commandBuffer, validation_error_map[VALIDATION_ERROR_16e00068]);
51595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
51605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
51615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (pInfo && pInfo->renderPass != VK_NULL_HANDLE) {
51629a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                auto renderPass = GetRenderPassState(dev_data, pInfo->renderPass);
516316387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes                if (renderPass) {
5164fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes                    if (pInfo->subpass >= renderPass->createInfo.subpassCount) {
51653251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
51669b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                        VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, HandleToUint64(commandBuffer), __LINE__,
5167315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                        VALIDATION_ERROR_0280006c, "DS",
51683251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                        "vkBeginCommandBuffer(): Secondary Command Buffers (0x%p) must have a subpass index (%d) "
51693251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                        "that is less than the number of subpasses (%d). %s",
51703251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                        commandBuffer, pInfo->subpass, renderPass->createInfo.subpassCount,
5171315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                        validation_error_map[VALIDATION_ERROR_0280006c]);
51725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    }
51735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
51745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
51755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
5176f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis        if (CB_RECORDING == cb_node->state) {
51773251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
5178315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_16e00062, "DS",
51793251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "vkBeginCommandBuffer(): Cannot call Begin on command buffer (0x%p"
51803251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            ") in the RECORDING state. Must first call vkEndCommandBuffer(). %s",
5181315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            commandBuffer, validation_error_map[VALIDATION_ERROR_16e00062]);
518246daa701a01b92ae19e3ee9e661d677128fe7e6dChris Forbes        } else if (CB_RECORDED == cb_node->state || CB_INVALID_COMPLETE == cb_node->state) {
5183f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis            VkCommandPool cmdPool = cb_node->createInfo.commandPool;
51849a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            auto pPool = GetCommandPoolNode(dev_data, cmdPool);
5185cd9a648074f67a1d44c15a056b90fc66da8ead17Chris Forbes            if (!(VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT & pPool->createFlags)) {
51863251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |=
51875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
5188315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_16e00064, "DS",
5189226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis                            "Call to vkBeginCommandBuffer() on command buffer (0x%p"
5190414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller                            ") attempts to implicitly reset cmdBuffer created from command pool (0x%" PRIxLEAST64
51914527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton                            ") that does NOT have the VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT bit set. %s",
5192315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            commandBuffer, HandleToUint64(cmdPool), validation_error_map[VALIDATION_ERROR_16e00064]);
51935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
51947cb00fa300f2563ae3e8eb506bca912c11216953John Zulauf            ResetCommandBufferState(dev_data, commandBuffer);
51955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
51965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // Set updated state here in case implicit reset occurs above
5197f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis        cb_node->state = CB_RECORDING;
5198f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis        cb_node->beginInfo = *pBeginInfo;
5199f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis        if (cb_node->beginInfo.pInheritanceInfo) {
5200f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis            cb_node->inheritanceInfo = *(cb_node->beginInfo.pInheritanceInfo);
5201f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis            cb_node->beginInfo.pInheritanceInfo = &cb_node->inheritanceInfo;
5202888e1d268098177fde4a2263e3d7b7cc415f1debMark Young            // If we are a secondary command-buffer and inheriting.  Update the items we should inherit.
5203f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis            if ((cb_node->createInfo.level != VK_COMMAND_BUFFER_LEVEL_PRIMARY) &&
5204f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis                (cb_node->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT)) {
52059a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                cb_node->activeRenderPass = GetRenderPassState(dev_data, cb_node->beginInfo.pInheritanceInfo->renderPass);
5206f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis                cb_node->activeSubpass = cb_node->beginInfo.pInheritanceInfo->subpass;
5207350841afb70bf8dcfc3c6ec6b66f0aaa639553a3Tobin Ehlis                cb_node->activeFramebuffer = cb_node->beginInfo.pInheritanceInfo->framebuffer;
5208f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis                cb_node->framebuffers.insert(cb_node->beginInfo.pInheritanceInfo->framebuffer);
5209888e1d268098177fde4a2263e3d7b7cc415f1debMark Young            }
52105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
52115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
5212b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
52133251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (skip) {
52145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        return VK_ERROR_VALIDATION_FAILED_EXT;
52155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
52164a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.BeginCommandBuffer(commandBuffer, pBeginInfo);
5217400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis
52185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
52195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
52205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
522189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL EndCommandBuffer(VkCommandBuffer commandBuffer) {
52223251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
522356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
5224ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
52259a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer);
52265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
52274527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton        if ((VK_COMMAND_BUFFER_LEVEL_PRIMARY == pCB->createInfo.level) ||
52284527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton            !(pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT)) {
5229fd61966f8d41b5bce15620b70563b7864cbb28feCody Northrop            // This needs spec clarification to update valid usage, see comments in PR:
5230fd61966f8d41b5bce15620b70563b7864cbb28feCody Northrop            // https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/pull/516#discussion_r63013756
5231315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis            skip |= insideRenderPass(dev_data, pCB, "vkEndCommandBuffer()", VALIDATION_ERROR_27400078);
5232fd61966f8d41b5bce15620b70563b7864cbb28feCody Northrop        }
52333251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateCmd(dev_data, pCB, CMD_END, "vkEndCommandBuffer()");
52345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (auto query : pCB->activeQueries) {
52353251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
5236315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_2740007a, "DS",
52373251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "Ending command buffer with in progress query: queryPool 0x%" PRIx64 ", index %d. %s",
5238315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(query.pool), query.index, validation_error_map[VALIDATION_ERROR_2740007a]);
52395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
52405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
52413251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (!skip) {
5242b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.unlock();
52430d9453d85335963d6cabfbf400b058dc905ea238Chris Forbes        auto result = dev_data->dispatch_table.EndCommandBuffer(commandBuffer);
5244b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.lock();
52455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (VK_SUCCESS == result) {
52465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            pCB->state = CB_RECORDED;
52475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
52480d9453d85335963d6cabfbf400b058dc905ea238Chris Forbes        return result;
52495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    } else {
52500d9453d85335963d6cabfbf400b058dc905ea238Chris Forbes        return VK_ERROR_VALIDATION_FAILED_EXT;
52515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
52525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
52535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5254bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL ResetCommandBuffer(VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags) {
52553251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
525656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
5257ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
52589a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer);
52595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    VkCommandPool cmdPool = pCB->createInfo.commandPool;
52609a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto pPool = GetCommandPoolNode(dev_data, cmdPool);
5261cd9a648074f67a1d44c15a056b90fc66da8ead17Chris Forbes    if (!(VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT & pPool->createFlags)) {
52623251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
5263315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_3260005c, "DS",
52643251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "Attempt to reset command buffer (0x%p) created from command pool (0x%" PRIxLEAST64
52653251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        ") that does NOT have the VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT bit set. %s",
5266315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        commandBuffer, HandleToUint64(cmdPool), validation_error_map[VALIDATION_ERROR_3260005c]);
52675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
5268315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis    skip |= checkCommandBufferInFlight(dev_data, pCB, "reset", VALIDATION_ERROR_3260005a);
5269b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
52703251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
52714a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.ResetCommandBuffer(commandBuffer, flags);
52725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
5273b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.lock();
52747cb00fa300f2563ae3e8eb506bca912c11216953John Zulauf        ResetCommandBufferState(dev_data, commandBuffer);
5275b9e992386a44404152747d66817a733aa127e281Jeremy Hayes        lock.unlock();
52765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
52775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
52785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
527993c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski
5280bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBindPipeline(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint,
5281bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                           VkPipeline pipeline) {
5282e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis    bool skip = false;
528356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
5284ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
52859a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer);
5286e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis    if (cb_state) {
5287baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt        skip |= ValidateCmdQueueFlags(dev_data, cb_state, "vkCmdBindPipeline()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT,
5288315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                      VALIDATION_ERROR_18002415);
528929f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis        skip |= ValidateCmd(dev_data, cb_state, CMD_BINDPIPELINE, "vkCmdBindPipeline()");
5290315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        // TODO: VALIDATION_ERROR_18000612 VALIDATION_ERROR_18000616
52915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5292374de4579f98cbbe8b616acb8e07a1a9c30402f8Chris Forbes        auto pipe_state = getPipelineState(dev_data, pipeline);
5293374de4579f98cbbe8b616acb8e07a1a9c30402f8Chris Forbes        if (VK_PIPELINE_BIND_POINT_GRAPHICS == pipelineBindPoint) {
529414494d322787d939bf6a9d3a03fc3938009592e0Chris Forbes            cb_state->status &= ~cb_state->static_status;
52959563e5dea7a06a2b937f917e0983f6cce3759681Chris Forbes            cb_state->static_status = MakeStaticStateMask(pipe_state->graphicsPipelineCI.ptr()->pDynamicState);
52969563e5dea7a06a2b937f917e0983f6cce3759681Chris Forbes            cb_state->status |= cb_state->static_status;
5297e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis        }
52989563e5dea7a06a2b937f917e0983f6cce3759681Chris Forbes        cb_state->lastBound[pipelineBindPoint].pipeline_state = pipe_state;
52999563e5dea7a06a2b937f917e0983f6cce3759681Chris Forbes        set_pipeline_state(pipe_state);
53009563e5dea7a06a2b937f917e0983f6cce3759681Chris Forbes        skip |= validate_dual_src_blend_feature(dev_data, pipe_state);
53019b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus        addCommandBufferBinding(&pipe_state->cb_bindings, {HandleToUint64(pipeline), kVulkanObjectTypePipeline}, cb_state);
53025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
5303b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
5304cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (!skip) dev_data->dispatch_table.CmdBindPipeline(commandBuffer, pipelineBindPoint, pipeline);
53055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
53065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5307bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetViewport(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount,
5308bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                          const VkViewport *pViewports) {
53093251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
531056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
5311ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
53129a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer);
53135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
5314315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetViewport()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_1e002415);
53153251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateCmd(dev_data, pCB, CMD_SETVIEWPORTSTATE, "vkCmdSetViewport()");
531676de58efdab4e3fb8911019e533bf80393bc5682Chris Forbes        if (pCB->static_status & CBSTATUS_VIEWPORT_SET) {
531776de58efdab4e3fb8911019e533bf80393bc5682Chris Forbes            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
531876de58efdab4e3fb8911019e533bf80393bc5682Chris Forbes                            HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_1e00098a, "DS",
531976de58efdab4e3fb8911019e533bf80393bc5682Chris Forbes                            "vkCmdSetViewport(): pipeline was created without VK_DYNAMIC_STATE_VIEWPORT flag. %s.",
532076de58efdab4e3fb8911019e533bf80393bc5682Chris Forbes                            validation_error_map[VALIDATION_ERROR_1e00098a]);
532176de58efdab4e3fb8911019e533bf80393bc5682Chris Forbes        }
53222843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes        if (!skip) {
53232843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes            pCB->viewportMask |= ((1u << viewportCount) - 1u) << firstViewport;
532476de58efdab4e3fb8911019e533bf80393bc5682Chris Forbes            pCB->status |= CBSTATUS_VIEWPORT_SET;
53252843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes        }
53265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
5327b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
53283251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (!skip) dev_data->dispatch_table.CmdSetViewport(commandBuffer, firstViewport, viewportCount, pViewports);
53295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
53305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5331bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetScissor(VkCommandBuffer commandBuffer, uint32_t firstScissor, uint32_t scissorCount,
5332bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                         const VkRect2D *pScissors) {
53333251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
533456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
5335ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
53369a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer);
53375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
5338315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetScissor()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_1d802415);
53393251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateCmd(dev_data, pCB, CMD_SETSCISSORSTATE, "vkCmdSetScissor()");
5340530cdb75eb81ef67b2093cea3c62737facfe91deChris Forbes        if (pCB->static_status & CBSTATUS_SCISSOR_SET) {
5341530cdb75eb81ef67b2093cea3c62737facfe91deChris Forbes            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
5342530cdb75eb81ef67b2093cea3c62737facfe91deChris Forbes                            HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_1d80049c, "DS",
5343530cdb75eb81ef67b2093cea3c62737facfe91deChris Forbes                            "vkCmdSetScissor(): pipeline was created without VK_DYNAMIC_STATE_SCISSOR flag. %s.",
5344530cdb75eb81ef67b2093cea3c62737facfe91deChris Forbes                            validation_error_map[VALIDATION_ERROR_1d80049c]);
5345530cdb75eb81ef67b2093cea3c62737facfe91deChris Forbes        }
53462843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes        if (!skip) {
53472843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes            pCB->scissorMask |= ((1u << scissorCount) - 1u) << firstScissor;
5348530cdb75eb81ef67b2093cea3c62737facfe91deChris Forbes            pCB->status |= CBSTATUS_SCISSOR_SET;
53492843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes        }
53505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
5351b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
53523251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (!skip) dev_data->dispatch_table.CmdSetScissor(commandBuffer, firstScissor, scissorCount, pScissors);
53535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
53545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
535589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdSetLineWidth(VkCommandBuffer commandBuffer, float lineWidth) {
53563251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
535756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
5358ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
53599a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer);
53605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
5361315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetLineWidth()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_1d602415);
53623251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateCmd(dev_data, pCB, CMD_SETLINEWIDTHSTATE, "vkCmdSetLineWidth()");
5363a27508babf63d50aea75883a3702979193c23683Mark Young
53642843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes        if (pCB->static_status & CBSTATUS_LINE_WIDTH_SET) {
53652843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
5366315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_1d600626, "DS",
53673251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "vkCmdSetLineWidth called but pipeline was created without VK_DYNAMIC_STATE_LINE_WIDTH "
53682843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes                            "flag. %s",
5369315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            validation_error_map[VALIDATION_ERROR_1d600626]);
5370a27508babf63d50aea75883a3702979193c23683Mark Young        }
53712843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes        if (!skip) {
53722843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes            pCB->status |= CBSTATUS_LINE_WIDTH_SET;
53732843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes        }
53745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
5375b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
53763251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (!skip) dev_data->dispatch_table.CmdSetLineWidth(commandBuffer, lineWidth);
53775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
53785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5379bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetDepthBias(VkCommandBuffer commandBuffer, float depthBiasConstantFactor, float depthBiasClamp,
5380bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                           float depthBiasSlopeFactor) {
53813251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
538256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
5383ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
53849a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer);
53855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
5386315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetDepthBias()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_1cc02415);
53873251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateCmd(dev_data, pCB, CMD_SETDEPTHBIASSTATE, "vkCmdSetDepthBias()");
53882843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes        if (pCB->static_status & CBSTATUS_DEPTH_BIAS_SET) {
53892843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
53902843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes                            HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_1cc0062a, "DS",
53912843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes                            "vkCmdSetDepthBias(): pipeline was created without VK_DYNAMIC_STATE_DEPTH_BIAS flag. %s.",
53922843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes                            validation_error_map[VALIDATION_ERROR_1cc0062a]);
53932843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes        }
5394434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski        if ((depthBiasClamp != 0.0) && (!dev_data->enabled_features.depthBiasClamp)) {
53953251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
5396315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_1cc0062c, "DS",
53973251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "vkCmdSetDepthBias(): the depthBiasClamp device feature is disabled: the depthBiasClamp "
53983251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "parameter must be set to 0.0. %s",
5399315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            validation_error_map[VALIDATION_ERROR_1cc0062c]);
5400434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski        }
54013251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        if (!skip) {
5402434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski            pCB->status |= CBSTATUS_DEPTH_BIAS_SET;
5403434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski        }
54045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
5405b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
54063251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (!skip)
54074a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdSetDepthBias(commandBuffer, depthBiasConstantFactor, depthBiasClamp, depthBiasSlopeFactor);
54085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
54095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
541089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdSetBlendConstants(VkCommandBuffer commandBuffer, const float blendConstants[4]) {
54113251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
541256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
5413ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
54149a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer);
54155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
5416315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetBlendConstants()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_1ca02415);
54173251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateCmd(dev_data, pCB, CMD_SETBLENDSTATE, "vkCmdSetBlendConstants()");
54182843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes        if (pCB->static_status & CBSTATUS_BLEND_CONSTANTS_SET) {
54192843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
54202843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes                            HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_1ca004c8, "DS",
54212843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes                            "vkCmdSetBlendConstants(): pipeline was created without VK_DYNAMIC_STATE_BLEND_CONSTANTS flag. %s.",
54222843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes                            validation_error_map[VALIDATION_ERROR_1ca004c8]);
54232843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes        }
54242843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes        if (!skip) {
54252843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes            pCB->status |= CBSTATUS_BLEND_CONSTANTS_SET;
54262843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes        }
54275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
5428b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
54293251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (!skip) dev_data->dispatch_table.CmdSetBlendConstants(commandBuffer, blendConstants);
54305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
54315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5432bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetDepthBounds(VkCommandBuffer commandBuffer, float minDepthBounds, float maxDepthBounds) {
54333251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
543456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
5435ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
54369a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer);
54375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
5438315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetDepthBounds()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_1ce02415);
54393251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateCmd(dev_data, pCB, CMD_SETDEPTHBOUNDSSTATE, "vkCmdSetDepthBounds()");
54402843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes        if (pCB->static_status & CBSTATUS_DEPTH_BOUNDS_SET) {
54412843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
54422843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes                            HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_1ce004ae, "DS",
54432843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes                            "vkCmdSetDepthBounds(): pipeline was created without VK_DYNAMIC_STATE_DEPTH_BOUNDS flag. %s.",
54442843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes                            validation_error_map[VALIDATION_ERROR_1ce004ae]);
54452843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes        }
54462843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes        if (!skip) {
54472843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes            pCB->status |= CBSTATUS_DEPTH_BOUNDS_SET;
54482843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes        }
54495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
5450b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
54513251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (!skip) dev_data->dispatch_table.CmdSetDepthBounds(commandBuffer, minDepthBounds, maxDepthBounds);
54525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
54535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5454bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetStencilCompareMask(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask,
5455bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                    uint32_t compareMask) {
54563251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
545756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
5458ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
54599a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer);
54605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
5461315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |=
5462315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis            ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetStencilCompareMask()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_1da02415);
54633251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateCmd(dev_data, pCB, CMD_SETSTENCILREADMASKSTATE, "vkCmdSetStencilCompareMask()");
54642843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes        if (pCB->static_status & CBSTATUS_STENCIL_READ_MASK_SET) {
54652843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
54662843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes                            HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_1da004b4, "DS",
54672843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes                            "vkCmdSetStencilCompareMask(): pipeline was created without VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK flag. %s.",
54682843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes                            validation_error_map[VALIDATION_ERROR_1da004b4]);
54692843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes        }
54702843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes        if (!skip) {
54712843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes            pCB->status |= CBSTATUS_STENCIL_READ_MASK_SET;
54722843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes        }
54735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
5474b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
54753251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (!skip) dev_data->dispatch_table.CmdSetStencilCompareMask(commandBuffer, faceMask, compareMask);
54765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
54775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5478bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetStencilWriteMask(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t writeMask) {
54793251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
548056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
5481ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
54829a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer);
54835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
5484315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |=
5485315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis            ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetStencilWriteMask()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_1de02415);
54863251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateCmd(dev_data, pCB, CMD_SETSTENCILWRITEMASKSTATE, "vkCmdSetStencilWriteMask()");
54872843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes        if (pCB->static_status & CBSTATUS_STENCIL_WRITE_MASK_SET) {
54882843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
54892843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes                            HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_1de004b6, "DS",
54902843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes                            "vkCmdSetStencilWriteMask(): pipeline was created without VK_DYNAMIC_STATE_STENCIL_WRITE_MASK flag. %s.",
54912843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes                            validation_error_map[VALIDATION_ERROR_1de004b6]);
54922843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes        }
54932843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes        if (!skip) {
54942843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes            pCB->status |= CBSTATUS_STENCIL_WRITE_MASK_SET;
54952843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes        }
54965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
5497b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
54983251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (!skip) dev_data->dispatch_table.CmdSetStencilWriteMask(commandBuffer, faceMask, writeMask);
54995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
55005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5501bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetStencilReference(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t reference) {
55023251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
550356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
5504ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
55059a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer);
55065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
5507315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |=
5508315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis            ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetStencilReference()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_1dc02415);
55093251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateCmd(dev_data, pCB, CMD_SETSTENCILREFERENCESTATE, "vkCmdSetStencilReference()");
55102843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes        if (pCB->static_status & CBSTATUS_STENCIL_REFERENCE_SET) {
55112843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
55122843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes                            HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_1dc004b8, "DS",
55132843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes                            "vkCmdSetStencilReference(): pipeline was created without VK_DYNAMIC_STATE_STENCIL_REFERENCE flag. %s.",
55142843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes                            validation_error_map[VALIDATION_ERROR_1dc004b8]);
55152843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes        }
55162843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes        if (!skip) {
55172843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes            pCB->status |= CBSTATUS_STENCIL_REFERENCE_SET;
55182843b4615e7c0fa78b6a5f1656f53fef5e89c607Chris Forbes        }
55195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
5520b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
55213251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (!skip) dev_data->dispatch_table.CmdSetStencilReference(commandBuffer, faceMask, reference);
55225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
55235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
552476ff99fdcc54e35ab1f3c34c3b093ccecb99e4dbMark Lobodzinskistatic void PreCallRecordCmdBindDescriptorSets(layer_data *device_data, GLOBAL_CB_NODE *cb_state,
552576ff99fdcc54e35ab1f3c34c3b093ccecb99e4dbMark Lobodzinski                                               VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t firstSet,
552676ff99fdcc54e35ab1f3c34c3b093ccecb99e4dbMark Lobodzinski                                               uint32_t setCount, const VkDescriptorSet *pDescriptorSets,
552776ff99fdcc54e35ab1f3c34c3b093ccecb99e4dbMark Lobodzinski                                               uint32_t dynamicOffsetCount, const uint32_t *pDynamicOffsets) {
5528ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski    uint32_t total_dynamic_descriptors = 0;
5529ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski    string error_string = "";
5530ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski    uint32_t last_set_index = firstSet + setCount - 1;
55312d4a3c28bf95f00fa2aac7d07288f6faf22208abMark Lobodzinski    auto last_bound = &cb_state->lastBound[pipelineBindPoint];
55322d4a3c28bf95f00fa2aac7d07288f6faf22208abMark Lobodzinski
55332d4a3c28bf95f00fa2aac7d07288f6faf22208abMark Lobodzinski    if (last_set_index >= last_bound->boundDescriptorSets.size()) {
55342d4a3c28bf95f00fa2aac7d07288f6faf22208abMark Lobodzinski        last_bound->boundDescriptorSets.resize(last_set_index + 1);
55352d4a3c28bf95f00fa2aac7d07288f6faf22208abMark Lobodzinski        last_bound->dynamicOffsets.resize(last_set_index + 1);
5536ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski    }
55372d4a3c28bf95f00fa2aac7d07288f6faf22208abMark Lobodzinski    auto old_final_bound_set = last_bound->boundDescriptorSets[last_set_index];
5538ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski    auto pipeline_layout = getPipelineLayout(device_data, layout);
5539ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski    for (uint32_t set_idx = 0; set_idx < setCount; set_idx++) {
5540ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski        cvdescriptorset::DescriptorSet *descriptor_set = GetSetNode(device_data, pDescriptorSets[set_idx]);
5541ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski        if (descriptor_set) {
55422d4a3c28bf95f00fa2aac7d07288f6faf22208abMark Lobodzinski            last_bound->pipeline_layout = *pipeline_layout;
55432d4a3c28bf95f00fa2aac7d07288f6faf22208abMark Lobodzinski
55442d4a3c28bf95f00fa2aac7d07288f6faf22208abMark Lobodzinski            if ((last_bound->boundDescriptorSets[set_idx + firstSet] != nullptr) &&
55452d4a3c28bf95f00fa2aac7d07288f6faf22208abMark Lobodzinski                last_bound->boundDescriptorSets[set_idx + firstSet]->IsPushDescriptor()) {
554654aae8da345cdc9b9db8ac81e3e03075db79cf9fJózef Kucia                last_bound->push_descriptor_set = nullptr;
55472d4a3c28bf95f00fa2aac7d07288f6faf22208abMark Lobodzinski                last_bound->boundDescriptorSets[set_idx + firstSet] = nullptr;
55482d4a3c28bf95f00fa2aac7d07288f6faf22208abMark Lobodzinski            }
55492d4a3c28bf95f00fa2aac7d07288f6faf22208abMark Lobodzinski
55502d4a3c28bf95f00fa2aac7d07288f6faf22208abMark Lobodzinski            last_bound->boundDescriptorSets[set_idx + firstSet] = descriptor_set;
5551ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski
5552ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski            auto set_dynamic_descriptor_count = descriptor_set->GetDynamicDescriptorCount();
55532d4a3c28bf95f00fa2aac7d07288f6faf22208abMark Lobodzinski            last_bound->dynamicOffsets[firstSet + set_idx].clear();
5554ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski            if (set_dynamic_descriptor_count) {
55552d4a3c28bf95f00fa2aac7d07288f6faf22208abMark Lobodzinski                last_bound->dynamicOffsets[firstSet + set_idx] =
5556ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                    std::vector<uint32_t>(pDynamicOffsets + total_dynamic_descriptors,
5557ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                                          pDynamicOffsets + total_dynamic_descriptors + set_dynamic_descriptor_count);
5558ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                total_dynamic_descriptors += set_dynamic_descriptor_count;
5559ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski            }
5560ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski        }
5561ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski        // For any previously bound sets, need to set them to "invalid" if they were disturbed by this update
5562ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski        if (firstSet > 0) {
5563ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski            for (uint32_t i = 0; i < firstSet; ++i) {
55642d4a3c28bf95f00fa2aac7d07288f6faf22208abMark Lobodzinski                if (last_bound->boundDescriptorSets[i] &&
55652d4a3c28bf95f00fa2aac7d07288f6faf22208abMark Lobodzinski                    !verify_set_layout_compatibility(last_bound->boundDescriptorSets[i], pipeline_layout, i, error_string)) {
55662d4a3c28bf95f00fa2aac7d07288f6faf22208abMark Lobodzinski                    last_bound->boundDescriptorSets[i] = VK_NULL_HANDLE;
55675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
5568ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski            }
5569ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski        }
5570ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski        // Check if newly last bound set invalidates any remaining bound sets
55712d4a3c28bf95f00fa2aac7d07288f6faf22208abMark Lobodzinski        if ((last_bound->boundDescriptorSets.size() - 1) > (last_set_index)) {
5572ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski            if (old_final_bound_set &&
5573ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                !verify_set_layout_compatibility(old_final_bound_set, pipeline_layout, last_set_index, error_string)) {
55742d4a3c28bf95f00fa2aac7d07288f6faf22208abMark Lobodzinski                last_bound->boundDescriptorSets.resize(last_set_index + 1);
5575ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski            }
5576ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski        }
5577ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski    }
5578ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski}
5579ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski
5580ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinskistatic bool PreCallValidateCmdBindDescriptorSets(layer_data *device_data, GLOBAL_CB_NODE *cb_state,
5581ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                                                 VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t firstSet,
5582ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                                                 uint32_t setCount, const VkDescriptorSet *pDescriptorSets,
5583ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                                                 uint32_t dynamicOffsetCount, const uint32_t *pDynamicOffsets) {
5584ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski    bool skip = false;
5585ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski    skip |= ValidateCmdQueueFlags(device_data, cb_state, "vkCmdBindDescriptorSets()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT,
5586ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                                  VALIDATION_ERROR_17c02415);
5587ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski    skip |= ValidateCmd(device_data, cb_state, CMD_BINDDESCRIPTORSETS, "vkCmdBindDescriptorSets()");
5588ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski    // Track total count of dynamic descriptor types to make sure we have an offset for each one
5589ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski    uint32_t total_dynamic_descriptors = 0;
5590ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski    string error_string = "";
5591ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski    uint32_t last_set_index = firstSet + setCount - 1;
5592ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski
5593ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski    if (last_set_index >= cb_state->lastBound[pipelineBindPoint].boundDescriptorSets.size()) {
5594ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski        cb_state->lastBound[pipelineBindPoint].boundDescriptorSets.resize(last_set_index + 1);
5595ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski        cb_state->lastBound[pipelineBindPoint].dynamicOffsets.resize(last_set_index + 1);
5596ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski    }
5597ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski    auto pipeline_layout = getPipelineLayout(device_data, layout);
5598ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski    for (uint32_t set_idx = 0; set_idx < setCount; set_idx++) {
5599ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski        cvdescriptorset::DescriptorSet *descriptor_set = GetSetNode(device_data, pDescriptorSets[set_idx]);
5600ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski        if (descriptor_set) {
5601ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski            if (!descriptor_set->IsUpdated() && (descriptor_set->GetTotalDescriptorCount() != 0)) {
5602ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT,
5603ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                                VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, HandleToUint64(pDescriptorSets[set_idx]), __LINE__,
5604ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                                DRAWSTATE_DESCRIPTOR_SET_NOT_UPDATED, "DS",
5605ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                                "Descriptor Set 0x%" PRIxLEAST64
5606ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                                " bound but it was never updated. You may want to either update it or not bind it.",
5607ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                                HandleToUint64(pDescriptorSets[set_idx]));
5608ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski            }
5609ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski            // Verify that set being bound is compatible with overlapping setLayout of pipelineLayout
5610ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski            if (!verify_set_layout_compatibility(descriptor_set, pipeline_layout, set_idx + firstSet, error_string)) {
5611ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                skip |=
5612ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                    log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
5613ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                            HandleToUint64(pDescriptorSets[set_idx]), __LINE__, VALIDATION_ERROR_17c002cc, "DS",
5614ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                            "descriptorSet #%u being bound is not compatible with overlapping descriptorSetLayout "
5615ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                            "at index %u of pipelineLayout 0x%" PRIxLEAST64 " due to: %s. %s",
5616ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                            set_idx, set_idx + firstSet, HandleToUint64(layout), error_string.c_str(),
5617ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                            validation_error_map[VALIDATION_ERROR_17c002cc]);
5618ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski            }
5619ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski
5620ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski            auto set_dynamic_descriptor_count = descriptor_set->GetDynamicDescriptorCount();
5621ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski
5622ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski            if (set_dynamic_descriptor_count) {
5623ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                // First make sure we won't overstep bounds of pDynamicOffsets array
5624ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                if ((total_dynamic_descriptors + set_dynamic_descriptor_count) > dynamicOffsetCount) {
5625ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                    skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
5626ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                                    VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, HandleToUint64(pDescriptorSets[set_idx]),
5627ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                                    __LINE__, DRAWSTATE_INVALID_DYNAMIC_OFFSET_COUNT, "DS",
5628ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                                    "descriptorSet #%u (0x%" PRIxLEAST64
5629ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                                    ") requires %u dynamicOffsets, but only %u dynamicOffsets are left in pDynamicOffsets "
5630ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                                    "array. There must be one dynamic offset for each dynamic descriptor being bound.",
5631ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                                    set_idx, HandleToUint64(pDescriptorSets[set_idx]), descriptor_set->GetDynamicDescriptorCount(),
5632ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                                    (dynamicOffsetCount - total_dynamic_descriptors));
5633ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                } else {  // Validate dynamic offsets and Dynamic Offset Minimums
5634ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                    uint32_t cur_dyn_offset = total_dynamic_descriptors;
5635ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                    for (uint32_t d = 0; d < descriptor_set->GetTotalDescriptorCount(); d++) {
5636ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                        if (descriptor_set->GetTypeFromGlobalIndex(d) == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) {
5637ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                            if (SafeModulo(pDynamicOffsets[cur_dyn_offset],
5638ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                                           device_data->phys_dev_properties.properties.limits.minUniformBufferOffsetAlignment) !=
5639ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                                0) {
5640ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                                skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
5641315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                                VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__,
5642315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                                VALIDATION_ERROR_17c002d4, "DS",
5643315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                                "vkCmdBindDescriptorSets(): pDynamicOffsets[%d] is %d but must be a multiple of "
5644315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                                "device limit minUniformBufferOffsetAlignment 0x%" PRIxLEAST64 ". %s",
5645315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                                cur_dyn_offset, pDynamicOffsets[cur_dyn_offset],
5646ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                                                device_data->phys_dev_properties.properties.limits.minUniformBufferOffsetAlignment,
5647315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                                validation_error_map[VALIDATION_ERROR_17c002d4]);
5648ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                            }
5649ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                            cur_dyn_offset++;
5650ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                        } else if (descriptor_set->GetTypeFromGlobalIndex(d) == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) {
5651ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                            if (SafeModulo(pDynamicOffsets[cur_dyn_offset],
5652ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                                           device_data->phys_dev_properties.properties.limits.minStorageBufferOffsetAlignment) !=
5653ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                                0) {
5654ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                                skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
5655315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                                VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__,
5656315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                                VALIDATION_ERROR_17c002d4, "DS",
5657315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                                "vkCmdBindDescriptorSets(): pDynamicOffsets[%d] is %d but must be a multiple of "
5658315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                                "device limit minStorageBufferOffsetAlignment 0x%" PRIxLEAST64 ". %s",
5659315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                                cur_dyn_offset, pDynamicOffsets[cur_dyn_offset],
5660ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                                                device_data->phys_dev_properties.properties.limits.minStorageBufferOffsetAlignment,
5661315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                                validation_error_map[VALIDATION_ERROR_17c002d4]);
5662ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski                            }
5663ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                            cur_dyn_offset++;
566472d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis                        }
566572d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis                    }
5666ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                    // Keep running total of dynamic descriptor count to verify at the end
5667ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                    total_dynamic_descriptors += set_dynamic_descriptor_count;
566872d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis                }
5669ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski            }
5670ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski        } else {
5671ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski            skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
56729b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(pDescriptorSets[set_idx]), __LINE__, DRAWSTATE_INVALID_SET, "DS",
56739b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            "Attempt to bind descriptor set 0x%" PRIxLEAST64 " that doesn't exist!",
56749b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(pDescriptorSets[set_idx]));
5675ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski        }
5676ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski    }
5677ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski    //  dynamicOffsetCount must equal the total number of dynamic descriptors in the sets being bound
5678ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski    if (total_dynamic_descriptors != dynamicOffsetCount) {
5679ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski        skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
5680ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                        HandleToUint64(cb_state->commandBuffer), __LINE__, VALIDATION_ERROR_17c002ce, "DS",
5681315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        "Attempting to bind %u descriptorSets with %u dynamic descriptors, but dynamicOffsetCount "
5682315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        "is %u. It should exactly match the number of dynamic descriptors. %s",
5683315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        setCount, total_dynamic_descriptors, dynamicOffsetCount, validation_error_map[VALIDATION_ERROR_17c002ce]);
56845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
5685ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski    return skip;
5686ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski}
5687ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski
5688ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBindDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint,
5689ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                                                 VkPipelineLayout layout, uint32_t firstSet, uint32_t setCount,
5690ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                                                 const VkDescriptorSet *pDescriptorSets, uint32_t dynamicOffsetCount,
5691ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                                                 const uint32_t *pDynamicOffsets) {
5692ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski    bool skip = false;
5693ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski    layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
5694ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski    unique_lock_t lock(global_lock);
5695ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski    GLOBAL_CB_NODE *cb_state = GetCBNode(device_data, commandBuffer);
5696ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski    assert(cb_state);
5697ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski    skip = PreCallValidateCmdBindDescriptorSets(device_data, cb_state, pipelineBindPoint, layout, firstSet, setCount,
5698ab727dc4a628d86d341d3cb9b915e8f82d2d8550Mark Lobodzinski                                                pDescriptorSets, dynamicOffsetCount, pDynamicOffsets);
569943cc253608e6daccdfa8cb795a98cfea91ef1582Mark Lobodzinski    if (!skip) {
570076ff99fdcc54e35ab1f3c34c3b093ccecb99e4dbMark Lobodzinski        PreCallRecordCmdBindDescriptorSets(device_data, cb_state, pipelineBindPoint, layout, firstSet, setCount, pDescriptorSets,
570176ff99fdcc54e35ab1f3c34c3b093ccecb99e4dbMark Lobodzinski                                           dynamicOffsetCount, pDynamicOffsets);
570276ff99fdcc54e35ab1f3c34c3b093ccecb99e4dbMark Lobodzinski        lock.unlock();
570343cc253608e6daccdfa8cb795a98cfea91ef1582Mark Lobodzinski        device_data->dispatch_table.CmdBindDescriptorSets(commandBuffer, pipelineBindPoint, layout, firstSet, setCount,
570443cc253608e6daccdfa8cb795a98cfea91ef1582Mark Lobodzinski                                                          pDescriptorSets, dynamicOffsetCount, pDynamicOffsets);
570576ff99fdcc54e35ab1f3c34c3b093ccecb99e4dbMark Lobodzinski    } else {
570676ff99fdcc54e35ab1f3c34c3b093ccecb99e4dbMark Lobodzinski        lock.unlock();
570776ff99fdcc54e35ab1f3c34c3b093ccecb99e4dbMark Lobodzinski
570843cc253608e6daccdfa8cb795a98cfea91ef1582Mark Lobodzinski    }
570943cc253608e6daccdfa8cb795a98cfea91ef1582Mark Lobodzinski}
571043cc253608e6daccdfa8cb795a98cfea91ef1582Mark Lobodzinski
57112d4a3c28bf95f00fa2aac7d07288f6faf22208abMark Lobodzinskistatic void PreCallRecordCmdPushDescriptorSetKHR(layer_data *device_data, VkCommandBuffer commandBuffer,
57122d4a3c28bf95f00fa2aac7d07288f6faf22208abMark Lobodzinski                                                 VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t set,
57132d4a3c28bf95f00fa2aac7d07288f6faf22208abMark Lobodzinski                                                 uint32_t descriptorWriteCount, const VkWriteDescriptorSet *pDescriptorWrites) {
571443cc253608e6daccdfa8cb795a98cfea91ef1582Mark Lobodzinski    auto cb_state = GetCBNode(device_data, commandBuffer);
57152d4a3c28bf95f00fa2aac7d07288f6faf22208abMark Lobodzinski
57162d4a3c28bf95f00fa2aac7d07288f6faf22208abMark Lobodzinski    if (set >= cb_state->lastBound[pipelineBindPoint].boundDescriptorSets.size()) {
57172d4a3c28bf95f00fa2aac7d07288f6faf22208abMark Lobodzinski        cb_state->lastBound[pipelineBindPoint].boundDescriptorSets.resize(set + 1);
57182d4a3c28bf95f00fa2aac7d07288f6faf22208abMark Lobodzinski        cb_state->lastBound[pipelineBindPoint].dynamicOffsets.resize(set + 1);
57192d4a3c28bf95f00fa2aac7d07288f6faf22208abMark Lobodzinski    }
5720e959c76d9d1825a781896df22e891cfb52e2b9c2Tobin Ehlis    const auto &layout_state = getPipelineLayout(device_data, layout);
5721e959c76d9d1825a781896df22e891cfb52e2b9c2Tobin Ehlis    std::unique_ptr<cvdescriptorset::DescriptorSet> new_desc{
5722e959c76d9d1825a781896df22e891cfb52e2b9c2Tobin Ehlis        new cvdescriptorset::DescriptorSet(0, 0, layout_state->set_layouts[set], device_data)};
57238938f7b0339a360aad99d6d33c7601465685dd64Chris Forbes    cb_state->lastBound[pipelineBindPoint].boundDescriptorSets[set] = new_desc.get();
572454aae8da345cdc9b9db8ac81e3e03075db79cf9fJózef Kucia    cb_state->lastBound[pipelineBindPoint].push_descriptor_set = std::move(new_desc);
57255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
57265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
572743839a7f8cf2180734f7b8ed3514eda94a63107aMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdPushDescriptorSetKHR(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint,
572843839a7f8cf2180734f7b8ed3514eda94a63107aMark Lobodzinski                                                   VkPipelineLayout layout, uint32_t set, uint32_t descriptorWriteCount,
572943839a7f8cf2180734f7b8ed3514eda94a63107aMark Lobodzinski                                                   const VkWriteDescriptorSet *pDescriptorWrites) {
573043839a7f8cf2180734f7b8ed3514eda94a63107aMark Lobodzinski    layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
573143cc253608e6daccdfa8cb795a98cfea91ef1582Mark Lobodzinski    unique_lock_t lock(global_lock);
57322d4a3c28bf95f00fa2aac7d07288f6faf22208abMark Lobodzinski    PreCallRecordCmdPushDescriptorSetKHR(device_data, commandBuffer, pipelineBindPoint, layout, set, descriptorWriteCount,
573343cc253608e6daccdfa8cb795a98cfea91ef1582Mark Lobodzinski                                         pDescriptorWrites);
573443cc253608e6daccdfa8cb795a98cfea91ef1582Mark Lobodzinski    lock.unlock();
573576ff99fdcc54e35ab1f3c34c3b093ccecb99e4dbMark Lobodzinski    device_data->dispatch_table.CmdPushDescriptorSetKHR(commandBuffer, pipelineBindPoint, layout, set, descriptorWriteCount,
573676ff99fdcc54e35ab1f3c34c3b093ccecb99e4dbMark Lobodzinski                                                        pDescriptorWrites);
573743839a7f8cf2180734f7b8ed3514eda94a63107aMark Lobodzinski}
573843839a7f8cf2180734f7b8ed3514eda94a63107aMark Lobodzinski
5739c30d253d86241c51fbd96d13f1590db5d9424894Chris Forbesstatic VkDeviceSize GetIndexAlignment(VkIndexType indexType) {
5740c30d253d86241c51fbd96d13f1590db5d9424894Chris Forbes    switch (indexType) {
5741c30d253d86241c51fbd96d13f1590db5d9424894Chris Forbes        case VK_INDEX_TYPE_UINT16:
5742c30d253d86241c51fbd96d13f1590db5d9424894Chris Forbes            return 2;
5743c30d253d86241c51fbd96d13f1590db5d9424894Chris Forbes        case VK_INDEX_TYPE_UINT32:
5744c30d253d86241c51fbd96d13f1590db5d9424894Chris Forbes            return 4;
5745c30d253d86241c51fbd96d13f1590db5d9424894Chris Forbes        default:
5746c30d253d86241c51fbd96d13f1590db5d9424894Chris Forbes            // Not a real index type. Express no alignment requirement here; we expect upper layer
5747c30d253d86241c51fbd96d13f1590db5d9424894Chris Forbes            // to have already picked up on the enum being nonsense.
5748c30d253d86241c51fbd96d13f1590db5d9424894Chris Forbes            return 1;
5749c30d253d86241c51fbd96d13f1590db5d9424894Chris Forbes    }
5750c30d253d86241c51fbd96d13f1590db5d9424894Chris Forbes}
5751c30d253d86241c51fbd96d13f1590db5d9424894Chris Forbes
5752bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBindIndexBuffer(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
5753bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                              VkIndexType indexType) {
5754946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski    bool skip = false;
575556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
5756ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
5757b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski
57589a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto buffer_state = GetBufferState(dev_data, buffer);
57599a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto cb_node = GetCBNode(dev_data, commandBuffer);
5760c30d253d86241c51fbd96d13f1590db5d9424894Chris Forbes    assert(cb_node);
5761c30d253d86241c51fbd96d13f1590db5d9424894Chris Forbes    assert(buffer_state);
5762c30d253d86241c51fbd96d13f1590db5d9424894Chris Forbes
5763c30d253d86241c51fbd96d13f1590db5d9424894Chris Forbes    skip |= ValidateBufferUsageFlags(dev_data, buffer_state, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, true,
5764c30d253d86241c51fbd96d13f1590db5d9424894Chris Forbes                                     VALIDATION_ERROR_17e00362, "vkCmdBindIndexBuffer()", "VK_BUFFER_USAGE_INDEX_BUFFER_BIT");
5765c30d253d86241c51fbd96d13f1590db5d9424894Chris Forbes    skip |= ValidateCmdQueueFlags(dev_data, cb_node, "vkCmdBindIndexBuffer()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_17e02415);
5766c30d253d86241c51fbd96d13f1590db5d9424894Chris Forbes    skip |= ValidateCmd(dev_data, cb_node, CMD_BINDINDEXBUFFER, "vkCmdBindIndexBuffer()");
5767c30d253d86241c51fbd96d13f1590db5d9424894Chris Forbes    skip |= ValidateMemoryIsBoundToBuffer(dev_data, buffer_state, "vkCmdBindIndexBuffer()", VALIDATION_ERROR_17e00364);
5768c30d253d86241c51fbd96d13f1590db5d9424894Chris Forbes    auto offset_align = GetIndexAlignment(indexType);
5769c30d253d86241c51fbd96d13f1590db5d9424894Chris Forbes    if (offset % offset_align) {
5770c30d253d86241c51fbd96d13f1590db5d9424894Chris Forbes        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
57717209a72b558b1defb8dcddb2dbe7646d323c01a3Chris Forbes                        HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_17e00360, "DS",
57727209a72b558b1defb8dcddb2dbe7646d323c01a3Chris Forbes                        "vkCmdBindIndexBuffer() offset (0x%" PRIxLEAST64 ") does not fall on alignment (%s) boundary. %s", offset,
57737209a72b558b1defb8dcddb2dbe7646d323c01a3Chris Forbes                        string_VkIndexType(indexType),
57747209a72b558b1defb8dcddb2dbe7646d323c01a3Chris Forbes                        validation_error_map[VALIDATION_ERROR_17e00360]);
57755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
5776c30d253d86241c51fbd96d13f1590db5d9424894Chris Forbes
5777c30d253d86241c51fbd96d13f1590db5d9424894Chris Forbes    if (skip)
5778c30d253d86241c51fbd96d13f1590db5d9424894Chris Forbes        return;
5779c30d253d86241c51fbd96d13f1590db5d9424894Chris Forbes
5780c30d253d86241c51fbd96d13f1590db5d9424894Chris Forbes    std::function<bool()> function = [=]() {
5781c30d253d86241c51fbd96d13f1590db5d9424894Chris Forbes        return ValidateBufferMemoryIsValid(dev_data, buffer_state, "vkCmdBindIndexBuffer()");
5782c30d253d86241c51fbd96d13f1590db5d9424894Chris Forbes    };
5783c30d253d86241c51fbd96d13f1590db5d9424894Chris Forbes    cb_node->queue_submit_functions.push_back(function);
5784c30d253d86241c51fbd96d13f1590db5d9424894Chris Forbes    cb_node->status |= CBSTATUS_INDEX_BUFFER_BOUND;
5785c30d253d86241c51fbd96d13f1590db5d9424894Chris Forbes
5786b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
5787c30d253d86241c51fbd96d13f1590db5d9424894Chris Forbes    dev_data->dispatch_table.CmdBindIndexBuffer(commandBuffer, buffer, offset, indexType);
57885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
57895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
57905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisvoid updateResourceTracking(GLOBAL_CB_NODE *pCB, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer *pBuffers) {
57915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    uint32_t end = firstBinding + bindingCount;
57925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB->currentDrawData.buffers.size() < end) {
57935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->currentDrawData.buffers.resize(end);
57945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
57955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < bindingCount; ++i) {
57965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->currentDrawData.buffers[i + firstBinding] = pBuffers[i];
57975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
57985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
57995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5800e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic inline void updateResourceTrackingOnDraw(GLOBAL_CB_NODE *pCB) { pCB->drawData.push_back(pCB->currentDrawData); }
58015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5802bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBindVertexBuffers(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount,
5803bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                const VkBuffer *pBuffers, const VkDeviceSize *pOffsets) {
5804946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski    bool skip = false;
580556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
5806ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
5807b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski
58089a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto cb_node = GetCBNode(dev_data, commandBuffer);
58097a31ef700e664f26961301bc5accadef33d86974Chris Forbes    assert(cb_node);
58107a31ef700e664f26961301bc5accadef33d86974Chris Forbes
58117a31ef700e664f26961301bc5accadef33d86974Chris Forbes    skip |= ValidateCmdQueueFlags(dev_data, cb_node, "vkCmdBindVertexBuffers()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_18202415);
58127a31ef700e664f26961301bc5accadef33d86974Chris Forbes    skip |= ValidateCmd(dev_data, cb_node, CMD_BINDVERTEXBUFFER, "vkCmdBindVertexBuffers()");
58137a31ef700e664f26961301bc5accadef33d86974Chris Forbes    for (uint32_t i = 0; i < bindingCount; ++i) {
58147a31ef700e664f26961301bc5accadef33d86974Chris Forbes        auto buffer_state = GetBufferState(dev_data, pBuffers[i]);
58157a31ef700e664f26961301bc5accadef33d86974Chris Forbes        assert(buffer_state);
58167a31ef700e664f26961301bc5accadef33d86974Chris Forbes        skip |= ValidateBufferUsageFlags(dev_data, buffer_state, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, true,
58177a31ef700e664f26961301bc5accadef33d86974Chris Forbes                                         VALIDATION_ERROR_182004e6, "vkCmdBindVertexBuffers()", "VK_BUFFER_USAGE_VERTEX_BUFFER_BIT");
58187a31ef700e664f26961301bc5accadef33d86974Chris Forbes        skip |= ValidateMemoryIsBoundToBuffer(dev_data, buffer_state, "vkCmdBindVertexBuffers()", VALIDATION_ERROR_182004e8);
58197a31ef700e664f26961301bc5accadef33d86974Chris Forbes        if (pOffsets[i] >= buffer_state->createInfo.size) {
58207a31ef700e664f26961301bc5accadef33d86974Chris Forbes            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT,
58217a31ef700e664f26961301bc5accadef33d86974Chris Forbes                            HandleToUint64(buffer_state->buffer), __LINE__, VALIDATION_ERROR_182004e4, "DS",
58227a31ef700e664f26961301bc5accadef33d86974Chris Forbes                            "vkCmdBindVertexBuffers() offset (0x%" PRIxLEAST64 ") is beyond the end of the buffer. %s",
58237a31ef700e664f26961301bc5accadef33d86974Chris Forbes                            pOffsets[i], validation_error_map[VALIDATION_ERROR_182004e4]);
58245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
58255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
58267a31ef700e664f26961301bc5accadef33d86974Chris Forbes
58277a31ef700e664f26961301bc5accadef33d86974Chris Forbes    if (skip)
58287a31ef700e664f26961301bc5accadef33d86974Chris Forbes        return;
58297a31ef700e664f26961301bc5accadef33d86974Chris Forbes
58307a31ef700e664f26961301bc5accadef33d86974Chris Forbes    for (uint32_t i = 0; i < bindingCount; ++i) {
58317a31ef700e664f26961301bc5accadef33d86974Chris Forbes        auto buffer_state = GetBufferState(dev_data, pBuffers[i]);
58327a31ef700e664f26961301bc5accadef33d86974Chris Forbes        assert(buffer_state);
58337a31ef700e664f26961301bc5accadef33d86974Chris Forbes        std::function<bool()> function = [=]() {
58347a31ef700e664f26961301bc5accadef33d86974Chris Forbes            return ValidateBufferMemoryIsValid(dev_data, buffer_state, "vkCmdBindVertexBuffers()");
58357a31ef700e664f26961301bc5accadef33d86974Chris Forbes        };
58367a31ef700e664f26961301bc5accadef33d86974Chris Forbes        cb_node->queue_submit_functions.push_back(function);
58377a31ef700e664f26961301bc5accadef33d86974Chris Forbes    }
58387a31ef700e664f26961301bc5accadef33d86974Chris Forbes
58397a31ef700e664f26961301bc5accadef33d86974Chris Forbes    updateResourceTracking(cb_node, firstBinding, bindingCount, pBuffers);
58407a31ef700e664f26961301bc5accadef33d86974Chris Forbes
5841b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
58427a31ef700e664f26961301bc5accadef33d86974Chris Forbes    dev_data->dispatch_table.CmdBindVertexBuffers(commandBuffer, firstBinding, bindingCount, pBuffers, pOffsets);
58435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
58445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
584525002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// Expects global_lock to be held by caller
58465569d6457ac22e7d245f3cdee045e71ffbc8b06eTobin Ehlisstatic void MarkStoreImagesAndBuffersAsWritten(layer_data *dev_data, GLOBAL_CB_NODE *pCB) {
58477a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis    for (auto imageView : pCB->updateImages) {
58489a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto view_state = GetImageViewState(dev_data, imageView);
5849cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        if (!view_state) continue;
5850249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis
58519a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto image_state = GetImageState(dev_data, view_state->create_info.image);
58521facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis        assert(image_state);
5853e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves        std::function<bool()> function = [=]() {
58541facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis            SetImageMemoryValid(dev_data, image_state, true);
5855e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves            return false;
58567a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis        };
5857d807198f24437c1b2478ff1d06a33ce4873a1451Tobin Ehlis        pCB->queue_submit_functions.push_back(function);
58587a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis    }
58597a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis    for (auto buffer : pCB->updateBuffers) {
58609a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto buffer_state = GetBufferState(dev_data, buffer);
58615cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis        assert(buffer_state);
5862e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves        std::function<bool()> function = [=]() {
58635cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis            SetBufferMemoryValid(dev_data, buffer_state, true);
5864e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves            return false;
58657a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis        };
5866d807198f24437c1b2478ff1d06a33ce4873a1451Tobin Ehlis        pCB->queue_submit_functions.push_back(function);
58675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
58685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
58695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5870ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis// Generic function to handle validation for all CmdDraw* type functions
5871ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool ValidateCmdDrawType(layer_data *dev_data, VkCommandBuffer cmd_buffer, bool indexed, VkPipelineBindPoint bind_point,
5872baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt                                CMD_TYPE cmd_type, GLOBAL_CB_NODE **cb_state, const char *caller, VkQueueFlags queue_flags,
5873baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt                                UNIQUE_VALIDATION_ERROR_CODE queue_flag_code, UNIQUE_VALIDATION_ERROR_CODE msg_code,
5874baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt                                UNIQUE_VALIDATION_ERROR_CODE const dynamic_state_msg_code) {
587558b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis    bool skip = false;
58769a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    *cb_state = GetCBNode(dev_data, cmd_buffer);
587758b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis    if (*cb_state) {
5878baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt        skip |= ValidateCmdQueueFlags(dev_data, *cb_state, caller, queue_flags, queue_flag_code);
5879ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis        skip |= ValidateCmd(dev_data, *cb_state, cmd_type, caller);
5880b4ab35582a070b18e22c0bd6cb8811c455f5b7ffTobin Ehlis        skip |= ValidateDrawState(dev_data, *cb_state, cmd_type, indexed, bind_point, caller, dynamic_state_msg_code);
588125d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis        skip |= (VK_PIPELINE_BIND_POINT_GRAPHICS == bind_point) ? outsideRenderPass(dev_data, *cb_state, caller, msg_code)
588225d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis                                                                : insideRenderPass(dev_data, *cb_state, caller, msg_code);
588358b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis    }
588458b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis    return skip;
588558b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis}
588658b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis
588725d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis// Generic function to handle state update for all CmdDraw* and CmdDispatch* type functions
58886b33c4e6a6f232fca84e0a6229106717b0012488Chris Forbesstatic void UpdateStateCmdDrawDispatchType(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point) {
5889ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis    UpdateDrawState(dev_data, cb_state, bind_point);
58902f921d33544c162dcb726fc3c7b915e89c02ff24Tobin Ehlis    MarkStoreImagesAndBuffersAsWritten(dev_data, cb_state);
589125d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis}
589225d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis
5893ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis// Generic function to handle state update for all CmdDraw* type functions
58946b33c4e6a6f232fca84e0a6229106717b0012488Chris Forbesstatic void UpdateStateCmdDrawType(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point) {
58956b33c4e6a6f232fca84e0a6229106717b0012488Chris Forbes    UpdateStateCmdDrawDispatchType(dev_data, cb_state, bind_point);
5896c0b225e42808ba8fada7a2f67ecd662e376ccf15Tobin Ehlis    updateResourceTrackingOnDraw(cb_state);
5897b68b13ed4952bce61f6ebb0023542660c26b0562Chris Forbes    cb_state->hasDrawCmd = true;
5898ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis}
5899ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis
5900ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool PreCallValidateCmdDraw(layer_data *dev_data, VkCommandBuffer cmd_buffer, bool indexed, VkPipelineBindPoint bind_point,
5901ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis                                   GLOBAL_CB_NODE **cb_state, const char *caller) {
5902baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt    return ValidateCmdDrawType(dev_data, cmd_buffer, indexed, bind_point, CMD_DRAW, cb_state, caller, VK_QUEUE_GRAPHICS_BIT,
5903315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                               VALIDATION_ERROR_1a202415, VALIDATION_ERROR_1a200017, VALIDATION_ERROR_1a200376);
5904ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis}
5905ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis
5906ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void PostCallRecordCmdDraw(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point) {
59076b33c4e6a6f232fca84e0a6229106717b0012488Chris Forbes    UpdateStateCmdDrawType(dev_data, cb_state, bind_point);
5908c0b225e42808ba8fada7a2f67ecd662e376ccf15Tobin Ehlis}
5909c0b225e42808ba8fada7a2f67ecd662e376ccf15Tobin Ehlis
591089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount,
591189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                   uint32_t firstVertex, uint32_t firstInstance) {
591256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
591358b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis    GLOBAL_CB_NODE *cb_state = nullptr;
5914ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
5915ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis    bool skip = PreCallValidateCmdDraw(dev_data, commandBuffer, false, VK_PIPELINE_BIND_POINT_GRAPHICS, &cb_state, "vkCmdDraw()");
5916b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
591758b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis    if (!skip) {
59184a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdDraw(commandBuffer, vertexCount, instanceCount, firstVertex, firstInstance);
5919c0b225e42808ba8fada7a2f67ecd662e376ccf15Tobin Ehlis        lock.lock();
5920ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis        PostCallRecordCmdDraw(dev_data, cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS);
5921c0b225e42808ba8fada7a2f67ecd662e376ccf15Tobin Ehlis        lock.unlock();
5922c0b225e42808ba8fada7a2f67ecd662e376ccf15Tobin Ehlis    }
59235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
59245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5925ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool PreCallValidateCmdDrawIndexed(layer_data *dev_data, VkCommandBuffer cmd_buffer, bool indexed,
5926ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis                                          VkPipelineBindPoint bind_point, GLOBAL_CB_NODE **cb_state, const char *caller) {
5927baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt    return ValidateCmdDrawType(dev_data, cmd_buffer, indexed, bind_point, CMD_DRAWINDEXED, cb_state, caller, VK_QUEUE_GRAPHICS_BIT,
5928315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                               VALIDATION_ERROR_1a402415, VALIDATION_ERROR_1a400017, VALIDATION_ERROR_1a40039c);
5929ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis}
5930ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis
5931ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void PostCallRecordCmdDrawIndexed(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point) {
59326b33c4e6a6f232fca84e0a6229106717b0012488Chris Forbes    UpdateStateCmdDrawType(dev_data, cb_state, bind_point);
5933ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis}
5934ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis
5935bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount,
5936bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                          uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance) {
593756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
5938ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis    GLOBAL_CB_NODE *cb_state = nullptr;
5939ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
5940ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis    bool skip = PreCallValidateCmdDrawIndexed(dev_data, commandBuffer, true, VK_PIPELINE_BIND_POINT_GRAPHICS, &cb_state,
5941ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis                                              "vkCmdDrawIndexed()");
5942b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
5943ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis    if (!skip) {
59444a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdDrawIndexed(commandBuffer, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
5945ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis        lock.lock();
5946ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis        PostCallRecordCmdDrawIndexed(dev_data, cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS);
5947ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis        lock.unlock();
5948ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis    }
59495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
59505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5951ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool PreCallValidateCmdDrawIndirect(layer_data *dev_data, VkCommandBuffer cmd_buffer, VkBuffer buffer, bool indexed,
5952ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis                                           VkPipelineBindPoint bind_point, GLOBAL_CB_NODE **cb_state, BUFFER_STATE **buffer_state,
5953ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis                                           const char *caller) {
5954315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis    bool skip =
5955315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        ValidateCmdDrawType(dev_data, cmd_buffer, indexed, bind_point, CMD_DRAWINDIRECT, cb_state, caller, VK_QUEUE_GRAPHICS_BIT,
5956315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            VALIDATION_ERROR_1aa02415, VALIDATION_ERROR_1aa00017, VALIDATION_ERROR_1aa003cc);
59579a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    *buffer_state = GetBufferState(dev_data, buffer);
5958315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis    skip |= ValidateMemoryIsBoundToBuffer(dev_data, *buffer_state, caller, VALIDATION_ERROR_1aa003b4);
595913c4316d0072cbc5bf3cd729abef4d114f3c96edMark Lobodzinski    // TODO: If the drawIndirectFirstInstance feature is not enabled, all the firstInstance members of the
596013c4316d0072cbc5bf3cd729abef4d114f3c96edMark Lobodzinski    // VkDrawIndirectCommand structures accessed by this command must be 0, which will require access to the contents of 'buffer'.
5961d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis    return skip;
5962d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis}
5963d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis
5964ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void PostCallRecordCmdDrawIndirect(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point,
5965ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis                                          BUFFER_STATE *buffer_state) {
59666b33c4e6a6f232fca84e0a6229106717b0012488Chris Forbes    UpdateStateCmdDrawType(dev_data, cb_state, bind_point);
5967d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis    AddCommandBufferBindingBuffer(dev_data, cb_state, buffer_state);
5968d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis}
5969d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis
5970bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count,
5971bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                           uint32_t stride) {
597256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
5973d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis    GLOBAL_CB_NODE *cb_state = nullptr;
5974d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis    BUFFER_STATE *buffer_state = nullptr;
5975ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
5976872a2f0ca3ffdeddfa7483e777191fa64b853892Tony Barbour    bool skip = PreCallValidateCmdDrawIndirect(dev_data, commandBuffer, buffer, false, VK_PIPELINE_BIND_POINT_GRAPHICS, &cb_state,
5977ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis                                               &buffer_state, "vkCmdDrawIndirect()");
5978b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
5979d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis    if (!skip) {
59804a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdDrawIndirect(commandBuffer, buffer, offset, count, stride);
5981d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis        lock.lock();
5982ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis        PostCallRecordCmdDrawIndirect(dev_data, cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, buffer_state);
5983d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis        lock.unlock();
5984d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis    }
59855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
59865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
5987ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool PreCallValidateCmdDrawIndexedIndirect(layer_data *dev_data, VkCommandBuffer cmd_buffer, VkBuffer buffer, bool indexed,
5988ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis                                                  VkPipelineBindPoint bind_point, GLOBAL_CB_NODE **cb_state,
5989ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis                                                  BUFFER_STATE **buffer_state, const char *caller) {
5990315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis    bool skip =
5991315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        ValidateCmdDrawType(dev_data, cmd_buffer, indexed, bind_point, CMD_DRAWINDEXEDINDIRECT, cb_state, caller,
5992315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_1a602415, VALIDATION_ERROR_1a600017, VALIDATION_ERROR_1a600434);
59939a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    *buffer_state = GetBufferState(dev_data, buffer);
5994315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis    skip |= ValidateMemoryIsBoundToBuffer(dev_data, *buffer_state, caller, VALIDATION_ERROR_1a60041c);
599513c4316d0072cbc5bf3cd729abef4d114f3c96edMark Lobodzinski    // TODO: If the drawIndirectFirstInstance feature is not enabled, all the firstInstance members of the
599613c4316d0072cbc5bf3cd729abef4d114f3c96edMark Lobodzinski    // VkDrawIndexedIndirectCommand structures accessed by this command must be 0, which will require access to the contents of
599713c4316d0072cbc5bf3cd729abef4d114f3c96edMark Lobodzinski    // 'buffer'.
59980c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis    return skip;
59990c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis}
60000c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis
6001ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void PostCallRecordCmdDrawIndexedIndirect(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point,
6002ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis                                                 BUFFER_STATE *buffer_state) {
60036b33c4e6a6f232fca84e0a6229106717b0012488Chris Forbes    UpdateStateCmdDrawType(dev_data, cb_state, bind_point);
60040c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis    AddCommandBufferBindingBuffer(dev_data, cb_state, buffer_state);
60050c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis}
60060c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis
6007bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
6008bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                  uint32_t count, uint32_t stride) {
600956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
60100c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis    GLOBAL_CB_NODE *cb_state = nullptr;
60110c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis    BUFFER_STATE *buffer_state = nullptr;
6012ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
60130c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis    bool skip = PreCallValidateCmdDrawIndexedIndirect(dev_data, commandBuffer, buffer, true, VK_PIPELINE_BIND_POINT_GRAPHICS,
6014ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis                                                      &cb_state, &buffer_state, "vkCmdDrawIndexedIndirect()");
6015b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
60160c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis    if (!skip) {
60174a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdDrawIndexedIndirect(commandBuffer, buffer, offset, count, stride);
60180c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis        lock.lock();
6019ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis        PostCallRecordCmdDrawIndexedIndirect(dev_data, cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, buffer_state);
60200c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis        lock.unlock();
60210c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis    }
60225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
60235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
6024ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool PreCallValidateCmdDispatch(layer_data *dev_data, VkCommandBuffer cmd_buffer, bool indexed,
6025ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis                                       VkPipelineBindPoint bind_point, GLOBAL_CB_NODE **cb_state, const char *caller) {
6026baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt    return ValidateCmdDrawType(dev_data, cmd_buffer, indexed, bind_point, CMD_DISPATCH, cb_state, caller, VK_QUEUE_COMPUTE_BIT,
6027315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                               VALIDATION_ERROR_19c02415, VALIDATION_ERROR_19c00017, VALIDATION_ERROR_UNDEFINED);
602825d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis}
602925d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis
6030ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void PostCallRecordCmdDispatch(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point) {
60316b33c4e6a6f232fca84e0a6229106717b0012488Chris Forbes    UpdateStateCmdDrawDispatchType(dev_data, cb_state, bind_point);
603225d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis}
603325d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis
603489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z) {
603556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
603625d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis    GLOBAL_CB_NODE *cb_state = nullptr;
6037ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
6038ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis    bool skip =
6039ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis        PreCallValidateCmdDispatch(dev_data, commandBuffer, false, VK_PIPELINE_BIND_POINT_COMPUTE, &cb_state, "vkCmdDispatch()");
6040b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
604125d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis    if (!skip) {
60424a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdDispatch(commandBuffer, x, y, z);
604325d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis        lock.lock();
6044ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis        PostCallRecordCmdDispatch(dev_data, cb_state, VK_PIPELINE_BIND_POINT_COMPUTE);
604525d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis        lock.unlock();
604625d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis    }
60475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
60485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
6049ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool PreCallValidateCmdDispatchIndirect(layer_data *dev_data, VkCommandBuffer cmd_buffer, VkBuffer buffer, bool indexed,
6050ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis                                               VkPipelineBindPoint bind_point, GLOBAL_CB_NODE **cb_state,
6051ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis                                               BUFFER_STATE **buffer_state, const char *caller) {
6052baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt    bool skip =
6053baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt        ValidateCmdDrawType(dev_data, cmd_buffer, indexed, bind_point, CMD_DISPATCHINDIRECT, cb_state, caller, VK_QUEUE_COMPUTE_BIT,
6054315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            VALIDATION_ERROR_1a002415, VALIDATION_ERROR_1a000017, VALIDATION_ERROR_UNDEFINED);
60559a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    *buffer_state = GetBufferState(dev_data, buffer);
6056315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis    skip |= ValidateMemoryIsBoundToBuffer(dev_data, *buffer_state, caller, VALIDATION_ERROR_1a000322);
605779c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis    return skip;
605879c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis}
605979c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis
6060ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void PostCallRecordCmdDispatchIndirect(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point,
6061ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis                                              BUFFER_STATE *buffer_state) {
60626b33c4e6a6f232fca84e0a6229106717b0012488Chris Forbes    UpdateStateCmdDrawDispatchType(dev_data, cb_state, bind_point);
606379c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis    AddCommandBufferBindingBuffer(dev_data, cb_state, buffer_state);
606479c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis}
606579c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis
6066bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset) {
606756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
606879c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis    GLOBAL_CB_NODE *cb_state = nullptr;
606979c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis    BUFFER_STATE *buffer_state = nullptr;
6070ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
60717433ab60c7ff16d37edb0f8b17b606ccd363e210Tobin Ehlis    bool skip = PreCallValidateCmdDispatchIndirect(dev_data, commandBuffer, buffer, false, VK_PIPELINE_BIND_POINT_COMPUTE,
6072ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis                                                   &cb_state, &buffer_state, "vkCmdDispatchIndirect()");
6073b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
607479c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis    if (!skip) {
60754a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdDispatchIndirect(commandBuffer, buffer, offset);
607679c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis        lock.lock();
6077ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis        PostCallRecordCmdDispatchIndirect(dev_data, cb_state, VK_PIPELINE_BIND_POINT_COMPUTE, buffer_state);
607879c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis        lock.unlock();
607979c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis    }
60805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
60815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
608289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdCopyBuffer(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer,
608389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                         uint32_t regionCount, const VkBufferCopy *pRegions) {
6084c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
6085ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
6086ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis
6087c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    auto cb_node = GetCBNode(device_data, commandBuffer);
6088c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    auto src_buffer_state = GetBufferState(device_data, srcBuffer);
6089c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    auto dst_buffer_state = GetBufferState(device_data, dstBuffer);
6090593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis
6091c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski    if (cb_node && src_buffer_state && dst_buffer_state) {
6092c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski        bool skip = PreCallValidateCmdCopyBuffer(device_data, cb_node, src_buffer_state, dst_buffer_state);
6093c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski        if (!skip) {
6094c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski            PreCallRecordCmdCopyBuffer(device_data, cb_node, src_buffer_state, dst_buffer_state);
6095c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski            lock.unlock();
6096c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski            device_data->dispatch_table.CmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, regionCount, pRegions);
6097c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski        }
6098ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    } else {
6099c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski        lock.unlock();
6100ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        assert(0);
61015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
61025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
61035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
6104bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdCopyImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout,
6105bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                        VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount,
6106bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                        const VkImageCopy *pRegions) {
61076a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    bool skip = false;
61086a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
6109ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
6110249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis
61116a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    auto cb_node = GetCBNode(device_data, commandBuffer);
61126a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    auto src_image_state = GetImageState(device_data, srcImage);
61136a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski    auto dst_image_state = GetImageState(device_data, dstImage);
61141facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis    if (cb_node && src_image_state && dst_image_state) {
61156a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        skip = PreCallValidateCmdCopyImage(device_data, cb_node, src_image_state, dst_image_state, regionCount, pRegions,
61166a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                           srcImageLayout, dstImageLayout);
61176a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        if (!skip) {
6118a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis            PreCallRecordCmdCopyImage(device_data, cb_node, src_image_state, dst_image_state, regionCount, pRegions, srcImageLayout,
6119a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis                                      dstImageLayout);
61206a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            lock.unlock();
61216a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski            device_data->dispatch_table.CmdCopyImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount,
61226a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski                                                     pRegions);
61235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
6124249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis    } else {
61256a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski        lock.unlock();
6126249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis        assert(0);
61275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
61285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
61295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
6130eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski// Validate that an image's sampleCount matches the requirement for a specific API call
613160568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinskibool ValidateImageSampleCount(layer_data *dev_data, IMAGE_STATE *image_state, VkSampleCountFlagBits sample_count,
613260568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski                              const char *location, UNIQUE_VALIDATION_ERROR_CODE msgCode) {
6133eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski    bool skip = false;
61341facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis    if (image_state->createInfo.samples != sample_count) {
61359b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus        skip = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
61369b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                       HandleToUint64(image_state->image), 0, msgCode, "DS",
61379b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                       "%s for image 0x%" PRIxLEAST64 " was created with a sample count of %s but must be %s. %s", location,
61389b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                       HandleToUint64(image_state->image), string_VkSampleCountFlagBits(image_state->createInfo.samples),
61399b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                       string_VkSampleCountFlagBits(sample_count), validation_error_map[msgCode]);
6140eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski    }
6141eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski    return skip;
6142eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski}
6143eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski
6144bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBlitImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout,
6145bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                        VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount,
6146bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                        const VkImageBlit *pRegions, VkFilter filter) {
614756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
6148ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
6149593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis
61509a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto cb_node = GetCBNode(dev_data, commandBuffer);
61519a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto src_image_state = GetImageState(dev_data, srcImage);
61529a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto dst_image_state = GetImageState(dev_data, dstImage);
61530dc51740dbd7b9f0ba7c071e0bf96f63d6d48c85Mark Lobodzinski
6154a99ceeafb2acc8ef0e18af2d1b24d5e1e68d5ee3Norbert Garnys    bool skip = PreCallValidateCmdBlitImage(dev_data, cb_node, src_image_state, dst_image_state, regionCount, pRegions,
6155a99ceeafb2acc8ef0e18af2d1b24d5e1e68d5ee3Norbert Garnys                                            srcImageLayout, dstImageLayout, filter);
61560dc51740dbd7b9f0ba7c071e0bf96f63d6d48c85Mark Lobodzinski
6157dca02371c9531e7a9a2a51decae1db4d297862c4Mark Lobodzinski    if (!skip) {
6158a99ceeafb2acc8ef0e18af2d1b24d5e1e68d5ee3Norbert Garnys        PreCallRecordCmdBlitImage(dev_data, cb_node, src_image_state, dst_image_state, regionCount, pRegions, srcImageLayout,
6159a99ceeafb2acc8ef0e18af2d1b24d5e1e68d5ee3Norbert Garnys                                  dstImageLayout);
6160eebd811afd800663f15fda8fc71bc203a03fe294Mark Lobodzinski        lock.unlock();
61614a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdBlitImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount,
61624a0754042cf090e131e9e769d8a3633c228625beChris Forbes                                              pRegions, filter);
61630dc51740dbd7b9f0ba7c071e0bf96f63d6d48c85Mark Lobodzinski    }
61645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
61655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
6166bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdCopyBufferToImage(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage,
6167bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                VkImageLayout dstImageLayout, uint32_t regionCount,
6168bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                const VkBufferImageCopy *pRegions) {
6169940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
6170ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
6171940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    bool skip = false;
6172940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    auto cb_node = GetCBNode(device_data, commandBuffer);
6173940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    auto src_buffer_state = GetBufferState(device_data, srcBuffer);
6174940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    auto dst_image_state = GetImageState(device_data, dstImage);
6175940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    if (cb_node && src_buffer_state && dst_image_state) {
6176940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski        skip = PreCallValidateCmdCopyBufferToImage(device_data, dstImageLayout, cb_node, src_buffer_state, dst_image_state,
617771c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                                                        regionCount, pRegions, "vkCmdCopyBufferToImage()");
6178ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    } else {
6179d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski        lock.unlock();
6180ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        assert(0);
6181e4d82c37d6c861b388dbc80297c18d6255858cb4Dave Houlton        // TODO: report VU01244 here, or put in object tracker?
61825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
6183940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    if (!skip) {
6184a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis        PreCallRecordCmdCopyBufferToImage(device_data, cb_node, src_buffer_state, dst_image_state, regionCount, pRegions,
6185a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis                                          dstImageLayout);
6186d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski        lock.unlock();
6187940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski        device_data->dispatch_table.CmdCopyBufferToImage(commandBuffer, srcBuffer, dstImage, dstImageLayout, regionCount, pRegions);
6188d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski    }
61895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
61905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
6191bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdCopyImageToBuffer(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout,
6192bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                VkBuffer dstBuffer, uint32_t regionCount, const VkBufferImageCopy *pRegions) {
6193940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    bool skip = false;
6194940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
6195ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
6196593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis
6197940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    auto cb_node = GetCBNode(device_data, commandBuffer);
6198940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    auto src_image_state = GetImageState(device_data, srcImage);
6199940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    auto dst_buffer_state = GetBufferState(device_data, dstBuffer);
6200940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    if (cb_node && src_image_state && dst_buffer_state) {
6201940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski        skip = PreCallValidateCmdCopyImageToBuffer(device_data, srcImageLayout, cb_node, src_image_state, dst_buffer_state,
620271c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski                                                        regionCount, pRegions, "vkCmdCopyImageToBuffer()");
6203ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    } else {
6204d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski        lock.unlock();
6205ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        assert(0);
6206e4d82c37d6c861b388dbc80297c18d6255858cb4Dave Houlton        // TODO: report VU01262 here, or put in object tracker?
62075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
6208940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski    if (!skip) {
6209a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis        PreCallRecordCmdCopyImageToBuffer(device_data, cb_node, src_image_state, dst_buffer_state, regionCount, pRegions,
6210a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis                                          srcImageLayout);
6211d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski        lock.unlock();
6212940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski        device_data->dispatch_table.CmdCopyImageToBuffer(commandBuffer, srcImage, srcImageLayout, dstBuffer, regionCount, pRegions);
6213d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski    }
62145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
62155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
6216e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlisstatic bool PreCallCmdUpdateBuffer(layer_data *device_data, const GLOBAL_CB_NODE *cb_state, const BUFFER_STATE *dst_buffer_state) {
6217e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis    bool skip = false;
6218e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis    skip |= ValidateMemoryIsBoundToBuffer(device_data, dst_buffer_state, "vkCmdUpdateBuffer()", VALIDATION_ERROR_1e400046);
6219e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis    // Validate that DST buffer has correct usage flags set
6220e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis    skip |= ValidateBufferUsageFlags(device_data, dst_buffer_state, VK_BUFFER_USAGE_TRANSFER_DST_BIT, true,
6221e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis                                     VALIDATION_ERROR_1e400044, "vkCmdUpdateBuffer()", "VK_BUFFER_USAGE_TRANSFER_DST_BIT");
6222e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis    skip |= ValidateCmdQueueFlags(device_data, cb_state, "vkCmdUpdateBuffer()",
6223e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis                                  VK_QUEUE_TRANSFER_BIT | VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, VALIDATION_ERROR_1e402415);
6224e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis    skip |= ValidateCmd(device_data, cb_state, CMD_UPDATEBUFFER, "vkCmdUpdateBuffer()");
6225e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis    skip |= insideRenderPass(device_data, cb_state, "vkCmdUpdateBuffer()", VALIDATION_ERROR_1e400017);
6226e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis    return skip;
6227e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis}
6228e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis
6229e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlisstatic void PostCallRecordCmdUpdateBuffer(layer_data *device_data, GLOBAL_CB_NODE *cb_state, BUFFER_STATE *dst_buffer_state) {
6230e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis    // Update bindings between buffer and cmd buffer
6231e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis    AddCommandBufferBindingBuffer(device_data, cb_state, dst_buffer_state);
6232e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis    std::function<bool()> function = [=]() {
6233e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis        SetBufferMemoryValid(device_data, dst_buffer_state, true);
6234e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis        return false;
6235e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis    };
6236d807198f24437c1b2478ff1d06a33ce4873a1451Tobin Ehlis    cb_state->queue_submit_functions.push_back(function);
6237e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis}
6238e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis
6239bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdUpdateBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset,
6240bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                           VkDeviceSize dataSize, const uint32_t *pData) {
62413251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
624256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
6243ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
6244593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis
6245e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis    auto cb_state = GetCBNode(dev_data, commandBuffer);
6246e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis    assert(cb_state);
62479a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto dst_buff_state = GetBufferState(dev_data, dstBuffer);
6248e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis    assert(dst_buff_state);
6249e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis    skip |= PreCallCmdUpdateBuffer(dev_data, cb_state, dst_buff_state);
6250b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
6251e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis    if (!skip) {
6252e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis        dev_data->dispatch_table.CmdUpdateBuffer(commandBuffer, dstBuffer, dstOffset, dataSize, pData);
6253e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis        lock.lock();
6254e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis        PostCallRecordCmdUpdateBuffer(dev_data, cb_state, dst_buff_state);
6255e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis        lock.unlock();
6256e08cf6348d38dc73e984f4ef9bc483f0aabb1914Tobin Ehlis    }
62575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
62585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
6259bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdFillBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset,
6260bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                         VkDeviceSize size, uint32_t data) {
626123bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
6262ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
626323bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    auto cb_node = GetCBNode(device_data, commandBuffer);
626423bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    auto buffer_state = GetBufferState(device_data, dstBuffer);
6265593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis
626623bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski    if (cb_node && buffer_state) {
626723bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski        bool skip = PreCallValidateCmdFillBuffer(device_data, cb_node, buffer_state);
626823bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski        if (!skip) {
626923bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski            PreCallRecordCmdFillBuffer(device_data, cb_node, buffer_state);
627023bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski            lock.unlock();
627123bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski            device_data->dispatch_table.CmdFillBuffer(commandBuffer, dstBuffer, dstOffset, size, data);
627223bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski        }
6273ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis    } else {
627423bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski        lock.unlock();
6275ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        assert(0);
62765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
62775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
62785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
62794028af23e688ab5730f48ab2244dd042e2eefaedMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdClearAttachments(VkCommandBuffer commandBuffer, uint32_t attachmentCount,
62804028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski                                               const VkClearAttachment *pAttachments, uint32_t rectCount,
62814028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski                                               const VkClearRect *pRects) {
62824028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski    bool skip = false;
628356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
62844028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski    {
6285ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes        lock_guard_t lock(global_lock);
62864028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski        skip = PreCallValidateCmdClearAttachments(dev_data, commandBuffer, attachmentCount, pAttachments, rectCount, pRects);
62874028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski    }
6288cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (!skip) dev_data->dispatch_table.CmdClearAttachments(commandBuffer, attachmentCount, pAttachments, rectCount, pRects);
62895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
62905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
62910482c55760707900fcd072f6895c121bcf055f6eMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdClearColorImage(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout,
62920482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski                                              const VkClearColorValue *pColor, uint32_t rangeCount,
62930482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski                                              const VkImageSubresourceRange *pRanges) {
629456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
6295ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
62960482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski
62970482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski    bool skip = PreCallValidateCmdClearColorImage(dev_data, commandBuffer, image, imageLayout, rangeCount, pRanges);
62980482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski    if (!skip) {
62990619dc1df076bfedcf0c999ceca3bdecd5ea5171Chris Forbes        PreCallRecordCmdClearImage(dev_data, commandBuffer, image, imageLayout, rangeCount, pRanges);
63000482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski        lock.unlock();
63010482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski        dev_data->dispatch_table.CmdClearColorImage(commandBuffer, image, imageLayout, pColor, rangeCount, pRanges);
63020482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski    }
63030482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski}
63040482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski
63050482c55760707900fcd072f6895c121bcf055f6eMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdClearDepthStencilImage(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout,
63060482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski                                                     const VkClearDepthStencilValue *pDepthStencil, uint32_t rangeCount,
63070482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski                                                     const VkImageSubresourceRange *pRanges) {
630856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
6309ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
63100482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski
63110482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski    bool skip = PreCallValidateCmdClearDepthStencilImage(dev_data, commandBuffer, image, imageLayout, rangeCount, pRanges);
63120482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski    if (!skip) {
63130619dc1df076bfedcf0c999ceca3bdecd5ea5171Chris Forbes        PreCallRecordCmdClearImage(dev_data, commandBuffer, image, imageLayout, rangeCount, pRanges);
63140482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski        lock.unlock();
63150482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski        dev_data->dispatch_table.CmdClearDepthStencilImage(commandBuffer, image, imageLayout, pDepthStencil, rangeCount, pRanges);
63167f8aa8f5abceedbb599ef69af1dfbb38c0df2660Slawomir Cygan    }
63175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
63185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
6319bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdResolveImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout,
6320bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                           VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount,
6321bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                           const VkImageResolve *pRegions) {
632256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
6323ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
6324593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis
63259a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto cb_node = GetCBNode(dev_data, commandBuffer);
63269a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto src_image_state = GetImageState(dev_data, srcImage);
63279a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto dst_image_state = GetImageState(dev_data, dstImage);
632809fe5ac5edaec7f0dbcc9fd696e68194569aea89Mark Lobodzinski
632925f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski    bool skip = PreCallValidateCmdResolveImage(dev_data, cb_node, src_image_state, dst_image_state, regionCount, pRegions);
633009fe5ac5edaec7f0dbcc9fd696e68194569aea89Mark Lobodzinski
633109fe5ac5edaec7f0dbcc9fd696e68194569aea89Mark Lobodzinski    if (!skip) {
63326c0400e625554ce7fddb833eeace0de19cfcc965Mark Lobodzinski        PreCallRecordCmdResolveImage(dev_data, cb_node, src_image_state, dst_image_state);
63336c0400e625554ce7fddb833eeace0de19cfcc965Mark Lobodzinski        lock.unlock();
63344a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdResolveImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount,
63354a0754042cf090e131e9e769d8a3633c228625beChris Forbes                                                 pRegions);
633609fe5ac5edaec7f0dbcc9fd696e68194569aea89Mark Lobodzinski    }
63375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
63385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
6339a8d1e377bdeaf61a3209cb997502da4356a185bbMike WeiblenVKAPI_ATTR void VKAPI_CALL GetImageSubresourceLayout(VkDevice device, VkImage image, const VkImageSubresource *pSubresource,
6340a8d1e377bdeaf61a3209cb997502da4356a185bbMike Weiblen                                                     VkSubresourceLayout *pLayout) {
6341a8d1e377bdeaf61a3209cb997502da4356a185bbMike Weiblen    layer_data *device_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
6342a8d1e377bdeaf61a3209cb997502da4356a185bbMike Weiblen
6343a8d1e377bdeaf61a3209cb997502da4356a185bbMike Weiblen    bool skip = PreCallValidateGetImageSubresourceLayout(device_data, image, pSubresource);
6344a8d1e377bdeaf61a3209cb997502da4356a185bbMike Weiblen    if (!skip) {
6345b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski        device_data->dispatch_table.GetImageSubresourceLayout(device, image, pSubresource, pLayout);
6346b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski    }
6347b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski}
6348b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski
6349b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentinebool setEventStageMask(VkQueue queue, VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) {
635056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
63519a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer);
6352b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine    if (pCB) {
6353b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine        pCB->eventToStageMap[event] = stageMask;
6354b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine    }
6355b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine    auto queue_data = dev_data->queueMap.find(queue);
6356b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine    if (queue_data != dev_data->queueMap.end()) {
6357b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine        queue_data->second.eventToStageMap[event] = stageMask;
6358b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine    }
6359b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine    return false;
6360b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine}
6361b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine
6362bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) {
63633251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
636456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
6365ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
63669a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer);
63675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
63683251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetEvent()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT,
6369315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                      VALIDATION_ERROR_1d402415);
63703251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateCmd(dev_data, pCB, CMD_SETEVENT, "vkCmdSetEvent()");
6371315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= insideRenderPass(dev_data, pCB, "vkCmdSetEvent()", VALIDATION_ERROR_1d400017);
6372315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= ValidateStageMaskGsTsEnables(dev_data, stageMask, "vkCmdSetEvent()", VALIDATION_ERROR_1d4008fc,
6373315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                             VALIDATION_ERROR_1d4008fe);
63749a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto event_state = GetEventNode(dev_data, event);
63754710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis        if (event_state) {
63769b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus            addCommandBufferBinding(&event_state->cb_bindings, {HandleToUint64(event), kVulkanObjectTypeEvent}, pCB);
63774710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis            event_state->cb_bindings.insert(pCB);
6378ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis        }
63795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->events.push_back(event);
6380c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine        if (!pCB->waitedEvents.count(event)) {
6381c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine            pCB->writeEventsBeforeWait.push_back(event);
6382c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine        }
6383f49bd2b5f4c968a3033b3e5099bbbcff51201575Chris Forbes        pCB->eventUpdates.emplace_back([=](VkQueue q){return setEventStageMask(q, commandBuffer, event, stageMask);});
63845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
6385b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
63863251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (!skip) dev_data->dispatch_table.CmdSetEvent(commandBuffer, event, stageMask);
63875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
63885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
6389bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdResetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) {
63903251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
639156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
6392ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
63939a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer);
63945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
63953251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdResetEvent()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT,
6396315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                      VALIDATION_ERROR_1c402415);
63973251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateCmd(dev_data, pCB, CMD_RESETEVENT, "vkCmdResetEvent()");
6398315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= insideRenderPass(dev_data, pCB, "vkCmdResetEvent()", VALIDATION_ERROR_1c400017);
6399315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= ValidateStageMaskGsTsEnables(dev_data, stageMask, "vkCmdResetEvent()", VALIDATION_ERROR_1c400904,
6400315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                             VALIDATION_ERROR_1c400906);
64019a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto event_state = GetEventNode(dev_data, event);
64024710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis        if (event_state) {
64039b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus            addCommandBufferBinding(&event_state->cb_bindings, {HandleToUint64(event), kVulkanObjectTypeEvent}, pCB);
64044710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis            event_state->cb_bindings.insert(pCB);
6405ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis        }
64065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        pCB->events.push_back(event);
6407c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine        if (!pCB->waitedEvents.count(event)) {
6408c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine            pCB->writeEventsBeforeWait.push_back(event);
6409c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine        }
6410315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        // TODO : Add check for VALIDATION_ERROR_32c008f8
6411f49bd2b5f4c968a3033b3e5099bbbcff51201575Chris Forbes        pCB->eventUpdates.emplace_back([=](VkQueue q){return setEventStageMask(q, commandBuffer, event, VkPipelineStageFlags(0));});
64125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
6413b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
64143251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (!skip) dev_data->dispatch_table.CmdResetEvent(commandBuffer, event, stageMask);
64155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
64165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
6417a54aea2a72be3bd84371773cc79a678816615587Tobin Ehlis// Return input pipeline stage flags, expanded for individual bits if VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT
6418a54aea2a72be3bd84371773cc79a678816615587Tobin Ehlisstatic VkPipelineStageFlags ExpandPipelineStageFlags(VkPipelineStageFlags inflags) {
6419a54aea2a72be3bd84371773cc79a678816615587Tobin Ehlis    return (inflags != VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT)
6420a54aea2a72be3bd84371773cc79a678816615587Tobin Ehlis               ? inflags
6421a54aea2a72be3bd84371773cc79a678816615587Tobin Ehlis               : (VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT | VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT | VK_PIPELINE_STAGE_VERTEX_INPUT_BIT |
6422a54aea2a72be3bd84371773cc79a678816615587Tobin Ehlis                  VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT |
6423a54aea2a72be3bd84371773cc79a678816615587Tobin Ehlis                  VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT |
6424a54aea2a72be3bd84371773cc79a678816615587Tobin Ehlis                  VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
6425a54aea2a72be3bd84371773cc79a678816615587Tobin Ehlis                  VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
6426a54aea2a72be3bd84371773cc79a678816615587Tobin Ehlis                  VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT);
6427a54aea2a72be3bd84371773cc79a678816615587Tobin Ehlis}
6428a54aea2a72be3bd84371773cc79a678816615587Tobin Ehlis
6429f384f33742c2b72888372332747298d08135ac92Tobin Ehlis// Verify image barrier image state and that the image is consistent with FB image
6430f384f33742c2b72888372332747298d08135ac92Tobin Ehlisstatic bool ValidateImageBarrierImage(layer_data *device_data, const char *funcName, GLOBAL_CB_NODE const *cb_state,
643179fc00370d55e7cbfd4052b579120e64b0a1a4beTobin Ehlis                                      VkFramebuffer framebuffer, uint32_t active_subpass, const safe_VkSubpassDescription &sub_desc,
643279fc00370d55e7cbfd4052b579120e64b0a1a4beTobin Ehlis                                      uint64_t rp_handle, uint32_t img_index, const VkImageMemoryBarrier &img_barrier) {
6433f384f33742c2b72888372332747298d08135ac92Tobin Ehlis    bool skip = false;
643479fc00370d55e7cbfd4052b579120e64b0a1a4beTobin Ehlis    const auto &fb_state = GetFramebufferState(device_data, framebuffer);
6435f384f33742c2b72888372332747298d08135ac92Tobin Ehlis    assert(fb_state);
6436f384f33742c2b72888372332747298d08135ac92Tobin Ehlis    const auto img_bar_image = img_barrier.image;
6437f384f33742c2b72888372332747298d08135ac92Tobin Ehlis    bool image_match = false;
6438f384f33742c2b72888372332747298d08135ac92Tobin Ehlis    bool sub_image_found = false;  // Do we find a corresponding subpass description
6439f384f33742c2b72888372332747298d08135ac92Tobin Ehlis    VkImageLayout sub_image_layout = VK_IMAGE_LAYOUT_UNDEFINED;
6440f384f33742c2b72888372332747298d08135ac92Tobin Ehlis    uint32_t attach_index = 0;
6441f384f33742c2b72888372332747298d08135ac92Tobin Ehlis    uint32_t index_count = 0;
6442f384f33742c2b72888372332747298d08135ac92Tobin Ehlis    // Verify that a framebuffer image matches barrier image
6443f384f33742c2b72888372332747298d08135ac92Tobin Ehlis    for (const auto &fb_attach : fb_state->attachments) {
6444f384f33742c2b72888372332747298d08135ac92Tobin Ehlis        if (img_bar_image == fb_attach.image) {
6445f384f33742c2b72888372332747298d08135ac92Tobin Ehlis            image_match = true;
6446f384f33742c2b72888372332747298d08135ac92Tobin Ehlis            attach_index = index_count;
6447f384f33742c2b72888372332747298d08135ac92Tobin Ehlis            break;
6448f384f33742c2b72888372332747298d08135ac92Tobin Ehlis        }
6449f384f33742c2b72888372332747298d08135ac92Tobin Ehlis        index_count++;
6450f384f33742c2b72888372332747298d08135ac92Tobin Ehlis    }
6451f384f33742c2b72888372332747298d08135ac92Tobin Ehlis    if (image_match) {  // Make sure subpass is referring to matching attachment
6452f384f33742c2b72888372332747298d08135ac92Tobin Ehlis        if (sub_desc.pDepthStencilAttachment && sub_desc.pDepthStencilAttachment->attachment == attach_index) {
6453f384f33742c2b72888372332747298d08135ac92Tobin Ehlis            sub_image_layout = sub_desc.pDepthStencilAttachment->layout;
6454f384f33742c2b72888372332747298d08135ac92Tobin Ehlis            sub_image_found = true;
6455f384f33742c2b72888372332747298d08135ac92Tobin Ehlis        } else {
6456f384f33742c2b72888372332747298d08135ac92Tobin Ehlis            for (uint32_t j = 0; j < sub_desc.colorAttachmentCount; ++j) {
6457f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                if (sub_desc.pColorAttachments && sub_desc.pColorAttachments[j].attachment == attach_index) {
6458f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                    sub_image_layout = sub_desc.pColorAttachments[j].layout;
6459f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                    sub_image_found = true;
6460f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                    break;
6461f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                } else if (sub_desc.pResolveAttachments && sub_desc.pResolveAttachments[j].attachment == attach_index) {
6462f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                    sub_image_layout = sub_desc.pResolveAttachments[j].layout;
6463f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                    sub_image_found = true;
6464f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                    break;
6465f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                }
6466f384f33742c2b72888372332747298d08135ac92Tobin Ehlis            }
6467f384f33742c2b72888372332747298d08135ac92Tobin Ehlis        }
6468f384f33742c2b72888372332747298d08135ac92Tobin Ehlis        if (!sub_image_found) {
6469f384f33742c2b72888372332747298d08135ac92Tobin Ehlis            skip |= log_msg(
6470f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT, rp_handle,
6471f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                __LINE__, VALIDATION_ERROR_1b800936, "CORE",
6472f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                "%s: Barrier pImageMemoryBarriers[%d].image (0x%" PRIx64
6473f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                ") is not referenced by the VkSubpassDescription for active subpass (%d) of current renderPass (0x%" PRIx64 "). %s",
6474f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                funcName, img_index, HandleToUint64(img_bar_image), active_subpass, rp_handle,
6475f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                validation_error_map[VALIDATION_ERROR_1b800936]);
6476f384f33742c2b72888372332747298d08135ac92Tobin Ehlis        }
6477f384f33742c2b72888372332747298d08135ac92Tobin Ehlis    } else {  // !image_match
6478f384f33742c2b72888372332747298d08135ac92Tobin Ehlis        auto const fb_handle = HandleToUint64(fb_state->framebuffer);
6479f384f33742c2b72888372332747298d08135ac92Tobin Ehlis        skip |=
6480f384f33742c2b72888372332747298d08135ac92Tobin Ehlis            log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT, fb_handle,
6481f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                    __LINE__, VALIDATION_ERROR_1b800936, "CORE",
6482f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                    "%s: Barrier pImageMemoryBarriers[%d].image (0x%" PRIx64
6483f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                    ") does not match an image from the current framebuffer (0x%" PRIx64 "). %s",
6484f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                    funcName, img_index, HandleToUint64(img_bar_image), fb_handle, validation_error_map[VALIDATION_ERROR_1b800936]);
6485f384f33742c2b72888372332747298d08135ac92Tobin Ehlis    }
6486f384f33742c2b72888372332747298d08135ac92Tobin Ehlis    if (img_barrier.oldLayout != img_barrier.newLayout) {
6487f384f33742c2b72888372332747298d08135ac92Tobin Ehlis        skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
6488f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                        HandleToUint64(cb_state->commandBuffer), __LINE__, VALIDATION_ERROR_1b80093a, "CORE",
6489f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                        "%s: As the Image Barrier for image 0x%" PRIx64
6490f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                        " is being executed within a render pass instance, oldLayout must equal newLayout yet they are "
6491f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                        "%s and %s. %s",
6492f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                        funcName, HandleToUint64(img_barrier.image), string_VkImageLayout(img_barrier.oldLayout),
6493f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                        string_VkImageLayout(img_barrier.newLayout), validation_error_map[VALIDATION_ERROR_1b80093a]);
6494f384f33742c2b72888372332747298d08135ac92Tobin Ehlis    } else {
6495f384f33742c2b72888372332747298d08135ac92Tobin Ehlis        if (sub_image_found && sub_image_layout != img_barrier.oldLayout) {
6496f384f33742c2b72888372332747298d08135ac92Tobin Ehlis            skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT,
6497f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                            rp_handle, __LINE__, VALIDATION_ERROR_1b800938, "CORE",
6498f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                            "%s: Barrier pImageMemoryBarriers[%d].image (0x%" PRIx64
6499f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                            ") is referenced by the VkSubpassDescription for active subpass (%d) of current renderPass (0x%" PRIx64
6500f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                            ") as having layout %s, but image barrier has layout %s. %s",
6501f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                            funcName, img_index, HandleToUint64(img_bar_image), active_subpass, rp_handle,
6502f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                            string_VkImageLayout(img_barrier.oldLayout), string_VkImageLayout(sub_image_layout),
6503f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                            validation_error_map[VALIDATION_ERROR_1b800938]);
6504f384f33742c2b72888372332747298d08135ac92Tobin Ehlis        }
6505f384f33742c2b72888372332747298d08135ac92Tobin Ehlis    }
6506f384f33742c2b72888372332747298d08135ac92Tobin Ehlis    return skip;
6507f384f33742c2b72888372332747298d08135ac92Tobin Ehlis}
6508f384f33742c2b72888372332747298d08135ac92Tobin Ehlis
65094cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis// Validate image barriers within a renderPass
6510f384f33742c2b72888372332747298d08135ac92Tobin Ehlisstatic bool ValidateRenderPassImageBarriers(layer_data *device_data, const char *funcName, GLOBAL_CB_NODE *cb_state,
65114cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                                            uint32_t active_subpass, const safe_VkSubpassDescription &sub_desc, uint64_t rp_handle,
65124cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                                            VkAccessFlags sub_src_access_mask, VkAccessFlags sub_dst_access_mask,
65134cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                                            uint32_t image_mem_barrier_count, const VkImageMemoryBarrier *image_barriers) {
6514a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis    bool skip = false;
65154cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis    for (uint32_t i = 0; i < image_mem_barrier_count; ++i) {
65164cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        const auto &img_barrier = image_barriers[i];
65174cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        const auto &img_src_access_mask = img_barrier.srcAccessMask;
65184cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        if (img_src_access_mask != (sub_src_access_mask & img_src_access_mask)) {
6519c1c43cc01e333f3762c65ce4ad926c33235583d2Tobin Ehlis            skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT,
65204cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            rp_handle, __LINE__, VALIDATION_ERROR_1b80092e, "CORE",
65214cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            "%s: Barrier pImageMemoryBarriers[%d].srcAccessMask(0x%X) is not a subset of VkSubpassDependency "
65224cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            "srcAccessMask(0x%X) of "
6523e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                            "subpass %d of renderPass 0x%" PRIx64 ". %s",
65244cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            funcName, i, img_src_access_mask, sub_src_access_mask, active_subpass, rp_handle,
65254cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            validation_error_map[VALIDATION_ERROR_1b80092e]);
6526e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis        }
65274cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        const auto &img_dst_access_mask = img_barrier.dstAccessMask;
65284cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        if (img_dst_access_mask != (sub_dst_access_mask & img_dst_access_mask)) {
6529c1c43cc01e333f3762c65ce4ad926c33235583d2Tobin Ehlis            skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT,
65304cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            rp_handle, __LINE__, VALIDATION_ERROR_1b800930, "CORE",
65314cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            "%s: Barrier pImageMemoryBarriers[%d].dstAccessMask(0x%X) is not a subset of VkSubpassDependency "
65324cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            "dstAccessMask(0x%X) of "
6533e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                            "subpass %d of renderPass 0x%" PRIx64 ". %s",
65344cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            funcName, i, img_dst_access_mask, sub_dst_access_mask, active_subpass, rp_handle,
65354cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            validation_error_map[VALIDATION_ERROR_1b800930]);
65365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
65378f2467c1db3d48bcfd09dd91188dcb0318fa5c43Tobin Ehlis        if (VK_QUEUE_FAMILY_IGNORED != img_barrier.srcQueueFamilyIndex ||
65388f2467c1db3d48bcfd09dd91188dcb0318fa5c43Tobin Ehlis            VK_QUEUE_FAMILY_IGNORED != img_barrier.dstQueueFamilyIndex) {
65398f2467c1db3d48bcfd09dd91188dcb0318fa5c43Tobin Ehlis            skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT,
65408f2467c1db3d48bcfd09dd91188dcb0318fa5c43Tobin Ehlis                            rp_handle, __LINE__, VALIDATION_ERROR_1b80093c, "CORE",
65418f2467c1db3d48bcfd09dd91188dcb0318fa5c43Tobin Ehlis                            "%s: Barrier pImageMemoryBarriers[%d].srcQueueFamilyIndex is %d and "
65428f2467c1db3d48bcfd09dd91188dcb0318fa5c43Tobin Ehlis                            "pImageMemoryBarriers[%d].dstQueueFamilyIndex is %d but both must be VK_QUEUE_FAMILY_IGNORED. %s",
65438f2467c1db3d48bcfd09dd91188dcb0318fa5c43Tobin Ehlis                            funcName, i, img_barrier.srcQueueFamilyIndex, i, img_barrier.dstQueueFamilyIndex,
65448f2467c1db3d48bcfd09dd91188dcb0318fa5c43Tobin Ehlis                            validation_error_map[VALIDATION_ERROR_1b80093c]);
65458f2467c1db3d48bcfd09dd91188dcb0318fa5c43Tobin Ehlis        }
6546f384f33742c2b72888372332747298d08135ac92Tobin Ehlis        // Secondary CBs can have null framebuffer so queue up validation in that case 'til FB is known
6547f384f33742c2b72888372332747298d08135ac92Tobin Ehlis        if (VK_NULL_HANDLE == cb_state->activeFramebuffer) {
6548f384f33742c2b72888372332747298d08135ac92Tobin Ehlis            assert(VK_COMMAND_BUFFER_LEVEL_SECONDARY == cb_state->createInfo.level);
6549f384f33742c2b72888372332747298d08135ac92Tobin Ehlis            // Secondary CB case w/o FB specified delay validation
655079fc00370d55e7cbfd4052b579120e64b0a1a4beTobin Ehlis            cb_state->cmd_execute_commands_functions.emplace_back([=](VkFramebuffer fb) {
655179fc00370d55e7cbfd4052b579120e64b0a1a4beTobin Ehlis                return ValidateImageBarrierImage(device_data, funcName, cb_state, fb, active_subpass, sub_desc, rp_handle, i,
6552f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                                                 img_barrier);
6553f384f33742c2b72888372332747298d08135ac92Tobin Ehlis            });
6554f384f33742c2b72888372332747298d08135ac92Tobin Ehlis        } else {
655579fc00370d55e7cbfd4052b579120e64b0a1a4beTobin Ehlis            skip |= ValidateImageBarrierImage(device_data, funcName, cb_state, cb_state->activeFramebuffer, active_subpass,
655679fc00370d55e7cbfd4052b579120e64b0a1a4beTobin Ehlis                                              sub_desc, rp_handle, i, img_barrier);
65573025e72bc2b727622969d036966f50057392551aTobin Ehlis        }
65584cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis    }
65594cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis    return skip;
65604cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis}
65614cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis
65624cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis// Validate VUs for Pipeline Barriers that are within a renderPass
65634cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis// Pre: cb_state->activeRenderPass must be a pointer to valid renderPass state
6564f384f33742c2b72888372332747298d08135ac92Tobin Ehlisstatic bool ValidateRenderPassPipelineBarriers(layer_data *device_data, const char *funcName, GLOBAL_CB_NODE *cb_state,
65654cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                                               VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask,
65664cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                                               VkDependencyFlags dependency_flags, uint32_t mem_barrier_count,
65674cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                                               const VkMemoryBarrier *mem_barriers, uint32_t buffer_mem_barrier_count,
65684cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                                               const VkBufferMemoryBarrier *buffer_mem_barriers, uint32_t image_mem_barrier_count,
65694cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                                               const VkImageMemoryBarrier *image_barriers) {
65704cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis    bool skip = false;
65714cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis    auto rp_state = cb_state->activeRenderPass;
65724cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis    const auto active_subpass = cb_state->activeSubpass;
65734cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis    auto rp_handle = HandleToUint64(rp_state->renderPass);
65744cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis    if (!rp_state->hasSelfDependency[active_subpass]) {
65754cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT,
65764cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                        rp_handle, __LINE__, VALIDATION_ERROR_1b800928, "CORE",
65774cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                        "%s: Barriers cannot be set during subpass %d of renderPass 0x%" PRIx64
65784cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                        " with no self-dependency specified. %s",
65794cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                        funcName, active_subpass, rp_handle, validation_error_map[VALIDATION_ERROR_1b800928]);
65804cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis    } else {
65814cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        assert(rp_state->subpass_to_dependency_index[cb_state->activeSubpass] != -1);
65824cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        // Grab ref to current subpassDescription up-front for use below
65834cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        const auto &sub_desc = rp_state->createInfo.pSubpasses[active_subpass];
65844cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        const auto &sub_dep = rp_state->createInfo.pDependencies[rp_state->subpass_to_dependency_index[active_subpass]];
65854cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        const auto &sub_src_stage_mask = ExpandPipelineStageFlags(sub_dep.srcStageMask);
65864cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        const auto &sub_dst_stage_mask = ExpandPipelineStageFlags(sub_dep.dstStageMask);
65874cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        if ((sub_src_stage_mask != VK_PIPELINE_STAGE_ALL_COMMANDS_BIT) &&
65884cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis            (src_stage_mask != (sub_src_stage_mask & src_stage_mask))) {
65894cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis            skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT,
65904cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            rp_handle, __LINE__, VALIDATION_ERROR_1b80092a, "CORE",
65914cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            "%s: Barrier srcStageMask(0x%X) is not a subset of VkSubpassDependency srcStageMask(0x%X) of "
65924cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            "subpass %d of renderPass 0x%" PRIx64 ". %s",
65934cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            funcName, src_stage_mask, sub_src_stage_mask, active_subpass, rp_handle,
65944cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            validation_error_map[VALIDATION_ERROR_1b80092a]);
65954cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        }
65964cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        if ((sub_dst_stage_mask != VK_PIPELINE_STAGE_ALL_COMMANDS_BIT) &&
65974cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis            (dst_stage_mask != (sub_dst_stage_mask & dst_stage_mask))) {
65984cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis            skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT,
65994cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            rp_handle, __LINE__, VALIDATION_ERROR_1b80092c, "CORE",
66004cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            "%s: Barrier dstStageMask(0x%X) is not a subset of VkSubpassDependency dstStageMask(0x%X) of "
66014cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            "subpass %d of renderPass 0x%" PRIx64 ". %s",
66024cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            funcName, dst_stage_mask, sub_dst_stage_mask, active_subpass, rp_handle,
66034cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            validation_error_map[VALIDATION_ERROR_1b80092c]);
66044cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        }
66054cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        if (0 != buffer_mem_barrier_count) {
66064cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis            skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT,
66074cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            rp_handle, __LINE__, VALIDATION_ERROR_1b800934, "CORE",
66084cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            "%s: bufferMemoryBarrierCount is non-zero (%d) for "
66094cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            "subpass %d of renderPass 0x%" PRIx64 ". %s",
66104cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            funcName, buffer_mem_barrier_count, active_subpass, rp_handle,
66114cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                            validation_error_map[VALIDATION_ERROR_1b800934]);
66124cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        }
66134cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        const auto &sub_src_access_mask = sub_dep.srcAccessMask;
66144cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        const auto &sub_dst_access_mask = sub_dep.dstAccessMask;
66154cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        for (uint32_t i = 0; i < mem_barrier_count; ++i) {
66164cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis            const auto &mb_src_access_mask = mem_barriers[i].srcAccessMask;
66174cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis            if (mb_src_access_mask != (sub_src_access_mask & mb_src_access_mask)) {
66184cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
66194cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                                VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT, rp_handle, __LINE__, VALIDATION_ERROR_1b80092e, "CORE",
66204cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                                "%s: Barrier pMemoryBarriers[%d].srcAccessMask(0x%X) is not a subset of VkSubpassDependency "
66214cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                                "srcAccessMask(0x%X) of "
66224cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                                "subpass %d of renderPass 0x%" PRIx64 ". %s",
66234cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                                funcName, i, mb_src_access_mask, sub_src_access_mask, active_subpass, rp_handle,
66244cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                                validation_error_map[VALIDATION_ERROR_1b80092e]);
66254cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis            }
66264cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis            const auto &mb_dst_access_mask = mem_barriers[i].dstAccessMask;
66274cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis            if (mb_dst_access_mask != (sub_dst_access_mask & mb_dst_access_mask)) {
66284cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
66294cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                                VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT, rp_handle, __LINE__, VALIDATION_ERROR_1b800930, "CORE",
66304cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                                "%s: Barrier pMemoryBarriers[%d].dstAccessMask(0x%X) is not a subset of VkSubpassDependency "
66314cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                                "dstAccessMask(0x%X) of "
66324cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                                "subpass %d of renderPass 0x%" PRIx64 ". %s",
66334cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                                funcName, i, mb_dst_access_mask, sub_dst_access_mask, active_subpass, rp_handle,
66344cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                                validation_error_map[VALIDATION_ERROR_1b800930]);
66354cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis            }
66364cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        }
66374cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis        skip |= ValidateRenderPassImageBarriers(device_data, funcName, cb_state, active_subpass, sub_desc, rp_handle,
66384cb62e790b73480ea81682b140a23d3717bd42abTobin Ehlis                                                sub_src_access_mask, sub_dst_access_mask, image_mem_barrier_count, image_barriers);
6639c1c43cc01e333f3762c65ce4ad926c33235583d2Tobin Ehlis        if (sub_dep.dependencyFlags != dependency_flags) {
6640c1c43cc01e333f3762c65ce4ad926c33235583d2Tobin Ehlis            skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT,
6641c1c43cc01e333f3762c65ce4ad926c33235583d2Tobin Ehlis                            rp_handle, __LINE__, VALIDATION_ERROR_1b800932, "CORE",
6642c1c43cc01e333f3762c65ce4ad926c33235583d2Tobin Ehlis                            "%s: dependencyFlags param (0x%X) does not equal VkSubpassDependency "
6643c1c43cc01e333f3762c65ce4ad926c33235583d2Tobin Ehlis                            "dependencyFlags value (0x%X) for "
6644c1c43cc01e333f3762c65ce4ad926c33235583d2Tobin Ehlis                            "subpass %d of renderPass 0x%" PRIx64 ". %s",
6645c1c43cc01e333f3762c65ce4ad926c33235583d2Tobin Ehlis                            funcName, dependency_flags, sub_dep.dependencyFlags, cb_state->activeSubpass, rp_handle,
6646c1c43cc01e333f3762c65ce4ad926c33235583d2Tobin Ehlis                            validation_error_map[VALIDATION_ERROR_1b800932]);
6647c1c43cc01e333f3762c65ce4ad926c33235583d2Tobin Ehlis        }
66485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
6649e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis    return skip;
6650e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis}
6651e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis
6652d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis// Array to mask individual accessMask to corresponding stageMask
6653d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis//  accessMask active bit position (0-31) maps to index
6654d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlisconst static VkPipelineStageFlags AccessMaskToPipeStage[20] = {
6655d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    // VK_ACCESS_INDIRECT_COMMAND_READ_BIT = 0
6656d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT,
6657d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    // VK_ACCESS_INDEX_READ_BIT = 1
6658d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    VK_PIPELINE_STAGE_VERTEX_INPUT_BIT,
6659d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    // VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT = 2
6660d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    VK_PIPELINE_STAGE_VERTEX_INPUT_BIT,
6661d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    // VK_ACCESS_UNIFORM_READ_BIT = 3
6662d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT |
6663d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis        VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT |
6664d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis        VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
6665d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    // VK_ACCESS_INPUT_ATTACHMENT_READ_BIT = 4
6666d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
6667d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    // VK_ACCESS_SHADER_READ_BIT = 5
6668d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT |
6669d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis        VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT |
6670d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis        VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
6671d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    // VK_ACCESS_SHADER_WRITE_BIT = 6
6672d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT |
6673d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis        VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT |
6674d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis        VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
6675d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    // VK_ACCESS_COLOR_ATTACHMENT_READ_BIT = 7
6676d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
6677d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    // VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT = 8
6678d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
6679d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    // VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT = 9
6680d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
6681d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    // VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT = 10
6682d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
6683d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    // VK_ACCESS_TRANSFER_READ_BIT = 11
6684d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    VK_PIPELINE_STAGE_TRANSFER_BIT,
6685d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    // VK_ACCESS_TRANSFER_WRITE_BIT = 12
6686d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    VK_PIPELINE_STAGE_TRANSFER_BIT,
6687d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    // VK_ACCESS_HOST_READ_BIT = 13
6688d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    VK_PIPELINE_STAGE_HOST_BIT,
6689d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    // VK_ACCESS_HOST_WRITE_BIT = 14
6690d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    VK_PIPELINE_STAGE_HOST_BIT,
6691d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    // VK_ACCESS_MEMORY_READ_BIT = 15
6692d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    VK_ACCESS_FLAG_BITS_MAX_ENUM,  // Always match
6693d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    // VK_ACCESS_MEMORY_WRITE_BIT = 16
6694d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    VK_ACCESS_FLAG_BITS_MAX_ENUM,  // Always match
6695d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    // VK_ACCESS_COMMAND_PROCESS_READ_BIT_NVX = 17
6696d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX,
6697d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    // VK_ACCESS_COMMAND_PROCESS_WRITE_BIT_NVX = 18
6698d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX,
6699d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis};
6700d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis
6701d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis// Verify that all bits of access_mask are supported by the src_stage_mask
6702d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlisstatic bool ValidateAccessMaskPipelineStage(VkAccessFlags access_mask, VkPipelineStageFlags stage_mask) {
6703d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    // Early out if all commands set, or access_mask NULL
6704d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    if ((stage_mask & VK_PIPELINE_STAGE_ALL_COMMANDS_BIT) || (0 == access_mask)) return true;
6705d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis
6706d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    stage_mask = ExpandPipelineStageFlags(stage_mask);
6707d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    int index = 0;
6708d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    // for each of the set bits in access_mask, make sure that supporting stage mask bit(s) are set
6709d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    while (access_mask) {
6710d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis        index = (u_ffs(access_mask) - 1);
6711d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis        assert(index >= 0);
6712d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis        // Must have "!= 0" compare to prevent warning from MSVC
6713d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis        if ((AccessMaskToPipeStage[index] & stage_mask) == 0) return false;  // early out
6714d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis        access_mask &= ~(1 << index);                                        // Mask off bit that's been checked
6715d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    }
6716d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    return true;
6717d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis}
6718d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis
6719e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlisstatic bool ValidateBarriers(layer_data *device_data, const char *funcName, GLOBAL_CB_NODE const *cb_state,
6720e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                             VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask, uint32_t memBarrierCount,
6721e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                             const VkMemoryBarrier *pMemBarriers, uint32_t bufferBarrierCount,
6722e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                             const VkBufferMemoryBarrier *pBufferMemBarriers, uint32_t imageMemBarrierCount,
6723e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                             const VkImageMemoryBarrier *pImageMemBarriers) {
6724e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis    bool skip = false;
6725d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    for (uint32_t i = 0; i < memBarrierCount; ++i) {
6726d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis        const auto &mem_barrier = pMemBarriers[i];
6727d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis        if (!ValidateAccessMaskPipelineStage(mem_barrier.srcAccessMask, src_stage_mask)) {
6728d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis            skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
6729d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis                            HandleToUint64(cb_state->commandBuffer), __LINE__, VALIDATION_ERROR_1b800940, "DS",
6730d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis                            "%s: pMemBarriers[%d].srcAccessMask (0x%X) is not supported by srcStageMask (0x%X). %s", funcName, i,
6731d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis                            mem_barrier.srcAccessMask, src_stage_mask, validation_error_map[VALIDATION_ERROR_1b800940]);
6732d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis        }
67331ce9b1e7d3dfd0841efede007022bdc960917008Tobin Ehlis        if (!ValidateAccessMaskPipelineStage(mem_barrier.dstAccessMask, dst_stage_mask)) {
67341ce9b1e7d3dfd0841efede007022bdc960917008Tobin Ehlis            skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
67351ce9b1e7d3dfd0841efede007022bdc960917008Tobin Ehlis                            HandleToUint64(cb_state->commandBuffer), __LINE__, VALIDATION_ERROR_1b800942, "DS",
67361ce9b1e7d3dfd0841efede007022bdc960917008Tobin Ehlis                            "%s: pMemBarriers[%d].dstAccessMask (0x%X) is not supported by dstStageMask (0x%X). %s", funcName, i,
67371ce9b1e7d3dfd0841efede007022bdc960917008Tobin Ehlis                            mem_barrier.dstAccessMask, dst_stage_mask, validation_error_map[VALIDATION_ERROR_1b800942]);
67381ce9b1e7d3dfd0841efede007022bdc960917008Tobin Ehlis        }
6739d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis    }
67405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < imageMemBarrierCount; ++i) {
67415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        auto mem_barrier = &pImageMemBarriers[i];
6742d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis        if (!ValidateAccessMaskPipelineStage(mem_barrier->srcAccessMask, src_stage_mask)) {
6743d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis            skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
6744d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis                            HandleToUint64(cb_state->commandBuffer), __LINE__, VALIDATION_ERROR_1b800940, "DS",
6745d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis                            "%s: pImageMemBarriers[%d].srcAccessMask (0x%X) is not supported by srcStageMask (0x%X). %s", funcName,
6746d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis                            i, mem_barrier->srcAccessMask, src_stage_mask, validation_error_map[VALIDATION_ERROR_1b800940]);
6747d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis        }
67481ce9b1e7d3dfd0841efede007022bdc960917008Tobin Ehlis        if (!ValidateAccessMaskPipelineStage(mem_barrier->dstAccessMask, dst_stage_mask)) {
67491ce9b1e7d3dfd0841efede007022bdc960917008Tobin Ehlis            skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
67501ce9b1e7d3dfd0841efede007022bdc960917008Tobin Ehlis                            HandleToUint64(cb_state->commandBuffer), __LINE__, VALIDATION_ERROR_1b800942, "DS",
67511ce9b1e7d3dfd0841efede007022bdc960917008Tobin Ehlis                            "%s: pImageMemBarriers[%d].dstAccessMask (0x%X) is not supported by dstStageMask (0x%X). %s", funcName,
67521ce9b1e7d3dfd0841efede007022bdc960917008Tobin Ehlis                            i, mem_barrier->dstAccessMask, dst_stage_mask, validation_error_map[VALIDATION_ERROR_1b800942]);
67531ce9b1e7d3dfd0841efede007022bdc960917008Tobin Ehlis        }
6754e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis        auto image_data = GetImageState(device_data, mem_barrier->image);
67558f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski        if (image_data) {
67568f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski            uint32_t src_q_f_index = mem_barrier->srcQueueFamilyIndex;
67578f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski            uint32_t dst_q_f_index = mem_barrier->dstQueueFamilyIndex;
67588f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski            if (image_data->createInfo.sharingMode == VK_SHARING_MODE_CONCURRENT) {
67598f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski                // srcQueueFamilyIndex and dstQueueFamilyIndex must both
67608f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski                // be VK_QUEUE_FAMILY_IGNORED
67618f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski                if ((src_q_f_index != VK_QUEUE_FAMILY_IGNORED) || (dst_q_f_index != VK_QUEUE_FAMILY_IGNORED)) {
6762e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                    skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
6763e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                                    VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, HandleToUint64(cb_state->commandBuffer),
6764e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                                    __LINE__, DRAWSTATE_INVALID_QUEUE_INDEX, "DS",
6765e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                                    "%s: Image Barrier for image 0x%" PRIx64
6766e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                                    " was created with sharingMode of "
6767e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                                    "VK_SHARING_MODE_CONCURRENT. Src and dst "
6768e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                                    "queueFamilyIndices must be VK_QUEUE_FAMILY_IGNORED.",
67699b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                    funcName, HandleToUint64(mem_barrier->image));
67708f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski                }
67718f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski            } else {
67728f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski                // Sharing mode is VK_SHARING_MODE_EXCLUSIVE. srcQueueFamilyIndex and
67738f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski                // dstQueueFamilyIndex must either both be VK_QUEUE_FAMILY_IGNORED,
67748f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski                // or both be a valid queue family
67758f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski                if (((src_q_f_index == VK_QUEUE_FAMILY_IGNORED) || (dst_q_f_index == VK_QUEUE_FAMILY_IGNORED)) &&
67768f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski                    (src_q_f_index != dst_q_f_index)) {
6777e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                    skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
6778e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                                    VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, HandleToUint64(cb_state->commandBuffer),
6779e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                                    __LINE__, DRAWSTATE_INVALID_QUEUE_INDEX, "DS",
6780e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                                    "%s: Image 0x%" PRIx64
6781e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                                    " was created with sharingMode "
6782e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                                    "of VK_SHARING_MODE_EXCLUSIVE. If one of src- or "
6783e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                                    "dstQueueFamilyIndex is VK_QUEUE_FAMILY_IGNORED, both "
6784e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                                    "must be.",
67859b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                    funcName, HandleToUint64(mem_barrier->image));
67868f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski                } else if (((src_q_f_index != VK_QUEUE_FAMILY_IGNORED) && (dst_q_f_index != VK_QUEUE_FAMILY_IGNORED)) &&
6787e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                           ((src_q_f_index >= device_data->phys_dev_properties.queue_family_properties.size()) ||
6788e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                            (dst_q_f_index >= device_data->phys_dev_properties.queue_family_properties.size()))) {
6789e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                    skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
6790e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                                    VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, HandleToUint64(cb_state->commandBuffer),
6791e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                                    __LINE__, DRAWSTATE_INVALID_QUEUE_INDEX, "DS",
67928f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski                                    "%s: Image 0x%" PRIx64
67938f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski                                    " was created with sharingMode "
67948f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski                                    "of VK_SHARING_MODE_EXCLUSIVE, but srcQueueFamilyIndex %d"
67958f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski                                    " or dstQueueFamilyIndex %d is greater than " PRINTF_SIZE_T_SPECIFIER
67968f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski                                    "queueFamilies crated for this device.",
67979b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                    funcName, HandleToUint64(mem_barrier->image), src_q_f_index, dst_q_f_index,
6798e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                                    device_data->phys_dev_properties.queue_family_properties.size());
67995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
68005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
68018f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski        }
68025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
68038f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski        if (mem_barrier->newLayout == VK_IMAGE_LAYOUT_UNDEFINED || mem_barrier->newLayout == VK_IMAGE_LAYOUT_PREINITIALIZED) {
6804e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis            skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
6805e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                            HandleToUint64(cb_state->commandBuffer), __LINE__, DRAWSTATE_INVALID_BARRIER, "DS",
6806df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                            "%s: Image Layout cannot be transitioned to UNDEFINED or "
6807df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                            "PREINITIALIZED.",
6808df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                            funcName);
68098f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski        }
68108f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski        if (image_data) {
68118f3c2a27e8e6feeb21d6be3b6f9f8d0606f67457Mark Lobodzinski            auto aspect_mask = mem_barrier->subresourceRange.aspectMask;
6812e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis            skip |= ValidateImageAspectMask(device_data, image_data->image, image_data->createInfo.format, aspect_mask, funcName);
681395b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski
681423c5a2092f724fef497a5c87a489f32c8fa51e58Petr Kraus            std::string param_name = "pImageMemoryBarriers[" + std::to_string(i) + "].subresourceRange";
6815e25e057866af155bd456003120aa6155530a0e5fPetr Kraus            skip |= ValidateImageBarrierSubresourceRange(device_data, image_data, mem_barrier->subresourceRange, funcName,
6816e25e057866af155bd456003120aa6155530a0e5fPetr Kraus                                                         param_name.c_str());
68175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
68185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
68192044b110851e8f1b75d6d406a0c88612476c63dbChris Forbes
68205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < bufferBarrierCount; ++i) {
68215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        auto mem_barrier = &pBufferMemBarriers[i];
6822cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        if (!mem_barrier) continue;
68235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
6824d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis        if (!ValidateAccessMaskPipelineStage(mem_barrier->srcAccessMask, src_stage_mask)) {
6825d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis            skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
6826d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis                            HandleToUint64(cb_state->commandBuffer), __LINE__, VALIDATION_ERROR_1b800940, "DS",
6827d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis                            "%s: pBufferMemBarriers[%d].srcAccessMask (0x%X) is not supported by srcStageMask (0x%X). %s", funcName,
6828d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis                            i, mem_barrier->srcAccessMask, src_stage_mask, validation_error_map[VALIDATION_ERROR_1b800940]);
6829d8aeb60bc6809b7ecac32f95db7f89d9c79a0a1cTobin Ehlis        }
68301ce9b1e7d3dfd0841efede007022bdc960917008Tobin Ehlis        if (!ValidateAccessMaskPipelineStage(mem_barrier->dstAccessMask, dst_stage_mask)) {
68311ce9b1e7d3dfd0841efede007022bdc960917008Tobin Ehlis            skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
68321ce9b1e7d3dfd0841efede007022bdc960917008Tobin Ehlis                            HandleToUint64(cb_state->commandBuffer), __LINE__, VALIDATION_ERROR_1b800942, "DS",
68331ce9b1e7d3dfd0841efede007022bdc960917008Tobin Ehlis                            "%s: pBufferMemBarriers[%d].dstAccessMask (0x%X) is not supported by dstStageMask (0x%X). %s", funcName,
68341ce9b1e7d3dfd0841efede007022bdc960917008Tobin Ehlis                            i, mem_barrier->dstAccessMask, dst_stage_mask, validation_error_map[VALIDATION_ERROR_1b800942]);
68351ce9b1e7d3dfd0841efede007022bdc960917008Tobin Ehlis        }
68365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // Validate buffer barrier queue family indices
68375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if ((mem_barrier->srcQueueFamilyIndex != VK_QUEUE_FAMILY_IGNORED &&
6838e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis             mem_barrier->srcQueueFamilyIndex >= device_data->phys_dev_properties.queue_family_properties.size()) ||
68395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            (mem_barrier->dstQueueFamilyIndex != VK_QUEUE_FAMILY_IGNORED &&
6840e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis             mem_barrier->dstQueueFamilyIndex >= device_data->phys_dev_properties.queue_family_properties.size())) {
6841e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis            skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
6842e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                            HandleToUint64(cb_state->commandBuffer), __LINE__, DRAWSTATE_INVALID_QUEUE_INDEX, "DS",
6843cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                            "%s: Buffer Barrier 0x%" PRIx64
6844cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                            " has QueueFamilyIndex greater "
6845a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis                            "than the number of QueueFamilies (" PRINTF_SIZE_T_SPECIFIER ") for this device.",
68469b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            funcName, HandleToUint64(mem_barrier->buffer),
6847e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                            device_data->phys_dev_properties.queue_family_properties.size());
68485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
68495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
6850e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis        auto buffer_state = GetBufferState(device_data, mem_barrier->buffer);
68515cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis        if (buffer_state) {
68525cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis            auto buffer_size = buffer_state->requirements.size;
68535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (mem_barrier->offset >= buffer_size) {
6854e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                skip |= log_msg(
6855e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                    device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
6856e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                    HandleToUint64(cb_state->commandBuffer), __LINE__, DRAWSTATE_INVALID_BARRIER, "DS",
6857e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                    "%s: Buffer Barrier 0x%" PRIx64 " has offset 0x%" PRIx64 " which is not less than total size 0x%" PRIx64 ".",
6858e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                    funcName, HandleToUint64(mem_barrier->buffer), HandleToUint64(mem_barrier->offset),
6859e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                    HandleToUint64(buffer_size));
6860df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski            } else if (mem_barrier->size != VK_WHOLE_SIZE && (mem_barrier->offset + mem_barrier->size > buffer_size)) {
6861df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                skip |=
6862e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                    log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
6863e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                            HandleToUint64(cb_state->commandBuffer), __LINE__, DRAWSTATE_INVALID_BARRIER, "DS",
6864df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                            "%s: Buffer Barrier 0x%" PRIx64 " has offset 0x%" PRIx64 " and size 0x%" PRIx64
6865df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                            " whose sum is greater than total size 0x%" PRIx64 ".",
68669b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            funcName, HandleToUint64(mem_barrier->buffer), HandleToUint64(mem_barrier->offset),
68679b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(mem_barrier->size), HandleToUint64(buffer_size));
68685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
68695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
68705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
6871a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis    return skip;
68725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
68735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
6874bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskibool validateEventStageMask(VkQueue queue, GLOBAL_CB_NODE *pCB, uint32_t eventCount, size_t firstEventIndex,
6875bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                            VkPipelineStageFlags sourceStageMask) {
68763251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
6877b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine    VkPipelineStageFlags stageMask = 0;
687856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map);
6879b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine    for (uint32_t i = 0; i < eventCount; ++i) {
68802ab14387df9b890fe4b13494ea249dd03cf898d2Chris Forbes        auto event = pCB->events[firstEventIndex + i];
6881b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine        auto queue_data = dev_data->queueMap.find(queue);
6882cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        if (queue_data == dev_data->queueMap.end()) return false;
68832ab14387df9b890fe4b13494ea249dd03cf898d2Chris Forbes        auto event_data = queue_data->second.eventToStageMap.find(event);
6884b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine        if (event_data != queue_data->second.eventToStageMap.end()) {
6885b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine            stageMask |= event_data->second;
6886b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine        } else {
68879a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            auto global_event_data = GetEventNode(dev_data, event);
68889556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis            if (!global_event_data) {
68893251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT,
68909b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                HandleToUint64(event), __LINE__, DRAWSTATE_INVALID_EVENT, "DS",
68919b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                "Event 0x%" PRIx64 " cannot be waited on if it has never been set.", HandleToUint64(event));
6892b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine            } else {
68939556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis                stageMask |= global_event_data->stageMask;
6894b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine            }
6895b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine        }
6896b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine    }
6897c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine    // TODO: Need to validate that host_bit is only set if set event is called
6898c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine    // but set event can be called at any time.
6899c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine    if (sourceStageMask != stageMask && sourceStageMask != (stageMask | VK_PIPELINE_STAGE_HOST_BIT)) {
69003251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
6901315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(pCB->commandBuffer), __LINE__, VALIDATION_ERROR_1e62d401, "DS",
69023251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "Submitting cmdbuffer with call to VkCmdWaitEvents "
69033251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "using srcStageMask 0x%X which must be the bitwise "
69043251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "OR of the stageMask parameters used in calls to "
69053251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "vkCmdSetEvent and VK_PIPELINE_STAGE_HOST_BIT if "
69063251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "used with vkSetEvent but instead is 0x%X. %s",
6907315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        sourceStageMask, stageMask, validation_error_map[VALIDATION_ERROR_1e62d401]);
6908b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine    }
69093251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
6910b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine}
6911b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine
691207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski// Note that we only check bits that HAVE required queueflags -- don't care entries are skipped
691307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinskistatic std::unordered_map<VkPipelineStageFlags, VkQueueFlags> supported_pipeline_stages_table = {
691407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    {VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX, VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT},
691507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    {VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT},
691607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    {VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_QUEUE_GRAPHICS_BIT},
691707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    {VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, VK_QUEUE_GRAPHICS_BIT},
691807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    {VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT, VK_QUEUE_GRAPHICS_BIT},
691907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    {VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT, VK_QUEUE_GRAPHICS_BIT},
692007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    {VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT, VK_QUEUE_GRAPHICS_BIT},
692107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    {VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_QUEUE_GRAPHICS_BIT},
692207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    {VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, VK_QUEUE_GRAPHICS_BIT},
692307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    {VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_QUEUE_GRAPHICS_BIT},
692407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_QUEUE_GRAPHICS_BIT},
692507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    {VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_QUEUE_COMPUTE_BIT},
692607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    {VK_PIPELINE_STAGE_TRANSFER_BIT, VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT},
692707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    {VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_QUEUE_GRAPHICS_BIT}};
692807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski
692907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinskistatic const VkPipelineStageFlags stage_flag_bit_array[] = {VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX,
693007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                                                            VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT,
693107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                                                            VK_PIPELINE_STAGE_VERTEX_INPUT_BIT,
693207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                                                            VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,
693307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                                                            VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT,
693407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                                                            VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT,
693507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                                                            VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT,
693607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                                                            VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
693707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                                                            VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,
693807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                                                            VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
693907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                                                            VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
694007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                                                            VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
694107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                                                            VK_PIPELINE_STAGE_TRANSFER_BIT,
694207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                                                            VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT};
694307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski
694407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinskibool CheckStageMaskQueueCompatibility(layer_data *dev_data, VkCommandBuffer command_buffer, VkPipelineStageFlags stage_mask,
694507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                                      VkQueueFlags queue_flags, const char *function, const char *src_or_dest,
694607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                                      UNIQUE_VALIDATION_ERROR_CODE error_code) {
694707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    bool skip = false;
694807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    // Lookup each bit in the stagemask and check for overlap between its table bits and queue_flags
694907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    for (const auto &item : stage_flag_bit_array) {
695007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski        if (stage_mask & item) {
695107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski            if ((supported_pipeline_stages_table[item] & queue_flags) == 0) {
695207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                skip |=
695307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
69549b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(command_buffer), __LINE__, error_code, "DL",
695507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                            "%s(): %s flag %s is not compatible with the queue family properties of this "
695607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                            "command buffer. %s",
695707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                            function, src_or_dest, string_VkPipelineStageFlagBits(static_cast<VkPipelineStageFlagBits>(item)),
695807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                            validation_error_map[error_code]);
695907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski            }
696007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski        }
696107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    }
696207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    return skip;
696307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski}
696407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski
6965e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlisbool ValidateStageMasksAgainstQueueCapabilities(layer_data *dev_data, GLOBAL_CB_NODE const *cb_state,
696607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                                                VkPipelineStageFlags source_stage_mask, VkPipelineStageFlags dest_stage_mask,
696707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                                                const char *function, UNIQUE_VALIDATION_ERROR_CODE error_code) {
696807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    bool skip = false;
696907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    uint32_t queue_family_index = dev_data->commandPoolMap[cb_state->createInfo.commandPool].queueFamilyIndex;
697056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(dev_data->physical_device), instance_layer_data_map);
69719a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto physical_device_state = GetPhysicalDeviceState(instance_data, dev_data->physical_device);
697207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski
697307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    // Any pipeline stage included in srcStageMask or dstStageMask must be supported by the capabilities of the queue family
697407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    // specified by the queueFamilyIndex member of the VkCommandPoolCreateInfo structure that was used to create the VkCommandPool
697507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    // that commandBuffer was allocated from, as specified in the table of supported pipeline stages.
697607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski
697707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    if (queue_family_index < physical_device_state->queue_family_properties.size()) {
697807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski        VkQueueFlags specified_queue_flags = physical_device_state->queue_family_properties[queue_family_index].queueFlags;
697907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski
698007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski        if ((source_stage_mask & VK_PIPELINE_STAGE_ALL_COMMANDS_BIT) == 0) {
698107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski            skip |= CheckStageMaskQueueCompatibility(dev_data, cb_state->commandBuffer, source_stage_mask, specified_queue_flags,
698207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                                                     function, "srcStageMask", error_code);
698307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski        }
698407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski        if ((dest_stage_mask & VK_PIPELINE_STAGE_ALL_COMMANDS_BIT) == 0) {
698507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski            skip |= CheckStageMaskQueueCompatibility(dev_data, cb_state->commandBuffer, dest_stage_mask, specified_queue_flags,
698607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski                                                     function, "dstStageMask", error_code);
698707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski        }
698807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    }
698907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski    return skip;
699007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski}
699107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski
6992d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent *pEvents,
6993d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski                                         VkPipelineStageFlags sourceStageMask, VkPipelineStageFlags dstStageMask,
6994d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski                                         uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
6995d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski                                         uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers,
6996d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski                                         uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers) {
6997d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski    bool skip = false;
699856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
6999ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
70009a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer);
7001d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski    if (cb_state) {
7002d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski        skip |= ValidateStageMasksAgainstQueueCapabilities(dev_data, cb_state, sourceStageMask, dstStageMask, "vkCmdWaitEvents",
7003315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                                           VALIDATION_ERROR_1e600918);
7004315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= ValidateStageMaskGsTsEnables(dev_data, sourceStageMask, "vkCmdWaitEvents()", VALIDATION_ERROR_1e60090e,
7005315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                             VALIDATION_ERROR_1e600912);
7006315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= ValidateStageMaskGsTsEnables(dev_data, dstStageMask, "vkCmdWaitEvents()", VALIDATION_ERROR_1e600910,
7007315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                             VALIDATION_ERROR_1e600914);
7008baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt        skip |= ValidateCmdQueueFlags(dev_data, cb_state, "vkCmdWaitEvents()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT,
7009315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                      VALIDATION_ERROR_1e602415);
7010ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski        skip |= ValidateCmd(dev_data, cb_state, CMD_WAITEVENTS, "vkCmdWaitEvents()");
7011e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis        skip |= ValidateBarriersToImages(dev_data, cb_state, imageMemoryBarrierCount, pImageMemoryBarriers, "vkCmdWaitEvents()");
7012e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis        skip |= ValidateBarriers(dev_data, "vkCmdWaitEvents()", cb_state, sourceStageMask, dstStageMask, memoryBarrierCount,
7013e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                                 pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount,
7014e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                                 pImageMemoryBarriers);
701557cd2a36adb056c73dbea3ab898b092123c2a2c1Chris Forbes        if (!skip) {
701657cd2a36adb056c73dbea3ab898b092123c2a2c1Chris Forbes            auto first_event_index = cb_state->events.size();
701757cd2a36adb056c73dbea3ab898b092123c2a2c1Chris Forbes            for (uint32_t i = 0; i < eventCount; ++i) {
701857cd2a36adb056c73dbea3ab898b092123c2a2c1Chris Forbes                auto event_state = GetEventNode(dev_data, pEvents[i]);
701957cd2a36adb056c73dbea3ab898b092123c2a2c1Chris Forbes                if (event_state) {
702057cd2a36adb056c73dbea3ab898b092123c2a2c1Chris Forbes                    addCommandBufferBinding(&event_state->cb_bindings, {HandleToUint64(pEvents[i]), kVulkanObjectTypeEvent}, cb_state);
702157cd2a36adb056c73dbea3ab898b092123c2a2c1Chris Forbes                    event_state->cb_bindings.insert(cb_state);
702257cd2a36adb056c73dbea3ab898b092123c2a2c1Chris Forbes                }
702357cd2a36adb056c73dbea3ab898b092123c2a2c1Chris Forbes                cb_state->waitedEvents.insert(pEvents[i]);
702457cd2a36adb056c73dbea3ab898b092123c2a2c1Chris Forbes                cb_state->events.push_back(pEvents[i]);
702557cd2a36adb056c73dbea3ab898b092123c2a2c1Chris Forbes            }
702657cd2a36adb056c73dbea3ab898b092123c2a2c1Chris Forbes            cb_state->eventUpdates.emplace_back([=](VkQueue q){
702757cd2a36adb056c73dbea3ab898b092123c2a2c1Chris Forbes                return validateEventStageMask(q, cb_state, eventCount, first_event_index, sourceStageMask);
702857cd2a36adb056c73dbea3ab898b092123c2a2c1Chris Forbes            });
702957cd2a36adb056c73dbea3ab898b092123c2a2c1Chris Forbes            TransitionImageLayouts(dev_data, commandBuffer, imageMemoryBarrierCount, pImageMemoryBarriers);
703057cd2a36adb056c73dbea3ab898b092123c2a2c1Chris Forbes        }
70315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
7032b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
7033d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski    if (!skip)
70344a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdWaitEvents(commandBuffer, eventCount, pEvents, sourceStageMask, dstStageMask,
70354a0754042cf090e131e9e769d8a3633c228625beChris Forbes                                               memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers,
70364a0754042cf090e131e9e769d8a3633c228625beChris Forbes                                               imageMemoryBarrierCount, pImageMemoryBarriers);
70375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
70385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
7039f384f33742c2b72888372332747298d08135ac92Tobin Ehlisstatic bool PreCallValidateCmdPipelineBarrier(layer_data *device_data, GLOBAL_CB_NODE *cb_state, VkPipelineStageFlags srcStageMask,
7040f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                                              VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags,
7041f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                                              uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
7042f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                                              uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers,
7043f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                                              uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers) {
704403122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski    bool skip = false;
704503122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski    skip |= ValidateStageMasksAgainstQueueCapabilities(device_data, cb_state, srcStageMask, dstStageMask, "vkCmdPipelineBarrier",
7046315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                                       VALIDATION_ERROR_1b80093e);
7047baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt    skip |= ValidateCmdQueueFlags(device_data, cb_state, "vkCmdPipelineBarrier()",
7048315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                  VK_QUEUE_TRANSFER_BIT | VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, VALIDATION_ERROR_1b802415);
704903122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski    skip |= ValidateCmd(device_data, cb_state, CMD_PIPELINEBARRIER, "vkCmdPipelineBarrier()");
7050315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis    skip |= ValidateStageMaskGsTsEnables(device_data, srcStageMask, "vkCmdPipelineBarrier()", VALIDATION_ERROR_1b800920,
7051315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                         VALIDATION_ERROR_1b800924);
7052315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis    skip |= ValidateStageMaskGsTsEnables(device_data, dstStageMask, "vkCmdPipelineBarrier()", VALIDATION_ERROR_1b800922,
7053315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                         VALIDATION_ERROR_1b800926);
7054e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis    if (cb_state->activeRenderPass) {
7055e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis        skip |= ValidateRenderPassPipelineBarriers(device_data, "vkCmdPipelineBarrier()", cb_state, srcStageMask, dstStageMask,
7056c1c43cc01e333f3762c65ce4ad926c33235583d2Tobin Ehlis                                                   dependencyFlags, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount,
7057e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                                                   pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers);
7058a287b10c55baa7d2d2ac891eb729666f988766eaTobin Ehlis        if (skip) return true;  // Early return to avoid redundant errors from below calls
7059e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis    }
7060a287b10c55baa7d2d2ac891eb729666f988766eaTobin Ehlis    skip |=
7061a287b10c55baa7d2d2ac891eb729666f988766eaTobin Ehlis        ValidateBarriersToImages(device_data, cb_state, imageMemoryBarrierCount, pImageMemoryBarriers, "vkCmdPipelineBarrier()");
7062e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis    skip |= ValidateBarriers(device_data, "vkCmdPipelineBarrier()", cb_state, srcStageMask, dstStageMask, memoryBarrierCount,
7063e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                             pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount,
7064e2d4ce3059fa77badeea63fa2003b83a04ca9c98Tobin Ehlis                             pImageMemoryBarriers);
706503122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski    return skip;
706603122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski}
706703122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski
70686f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinskistatic void PreCallRecordCmdPipelineBarrier(layer_data *device_data, GLOBAL_CB_NODE *cb_state, VkCommandBuffer commandBuffer,
70696f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski                                            uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers) {
70706f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski    TransitionImageLayouts(device_data, commandBuffer, imageMemoryBarrierCount, pImageMemoryBarriers);
70716f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski}
70726f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski
7073d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdPipelineBarrier(VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask,
7074d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski                                              VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags,
7075d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski                                              uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
7076d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski                                              uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers,
7077d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski                                              uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers) {
7078d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski    bool skip = false;
70796f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski    layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
7080ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
70816f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski    GLOBAL_CB_NODE *cb_state = GetCBNode(device_data, commandBuffer);
7082d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski    if (cb_state) {
7083c1c43cc01e333f3762c65ce4ad926c33235583d2Tobin Ehlis        skip |= PreCallValidateCmdPipelineBarrier(device_data, cb_state, srcStageMask, dstStageMask, dependencyFlags,
7084c1c43cc01e333f3762c65ce4ad926c33235583d2Tobin Ehlis                                                  memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount,
7085c1c43cc01e333f3762c65ce4ad926c33235583d2Tobin Ehlis                                                  pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers);
70866f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski        if (!skip) {
70876f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski            PreCallRecordCmdPipelineBarrier(device_data, cb_state, commandBuffer, imageMemoryBarrierCount, pImageMemoryBarriers);
70886f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski        }
70896f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski    } else {
70906f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski        assert(0);
70915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
7092b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
7093a79957f762f6fc6b74c25cb94d35a3fc36967471Tony Barbour    if (!skip) {
7094a79957f762f6fc6b74c25cb94d35a3fc36967471Tony Barbour        device_data->dispatch_table.CmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, memoryBarrierCount,
7095a79957f762f6fc6b74c25cb94d35a3fc36967471Tony Barbour                                                       pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers,
7096a79957f762f6fc6b74c25cb94d35a3fc36967471Tony Barbour                                                       imageMemoryBarrierCount, pImageMemoryBarriers);
7097a79957f762f6fc6b74c25cb94d35a3fc36967471Tony Barbour    }
70985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
70995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
710043ec3f090ca979777b306abe7c25662b9429e06dChris Forbesstatic bool setQueryState(VkQueue queue, VkCommandBuffer commandBuffer, QueryObject object, bool value) {
710156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
71029a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer);
7103d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine    if (pCB) {
7104d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine        pCB->queryToStateMap[object] = value;
7105d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine    }
7106d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine    auto queue_data = dev_data->queueMap.find(queue);
7107d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine    if (queue_data != dev_data->queueMap.end()) {
7108d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine        queue_data->second.queryToStateMap[object] = value;
7109d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine    }
7110d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine    return false;
7111d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine}
7112d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine
7113bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBeginQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t slot, VkFlags flags) {
71143251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
711556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
7116ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
71179a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer);
71185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
71193251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdBeginQuery()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT,
7120315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                      VALIDATION_ERROR_17802415);
71213251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateCmd(dev_data, pCB, CMD_BEGINQUERY, "vkCmdBeginQuery()");
712243ec3f090ca979777b306abe7c25662b9429e06dChris Forbes    }
712343ec3f090ca979777b306abe7c25662b9429e06dChris Forbes    lock.unlock();
712443ec3f090ca979777b306abe7c25662b9429e06dChris Forbes
712543ec3f090ca979777b306abe7c25662b9429e06dChris Forbes    if (skip) return;
712643ec3f090ca979777b306abe7c25662b9429e06dChris Forbes
712743ec3f090ca979777b306abe7c25662b9429e06dChris Forbes    dev_data->dispatch_table.CmdBeginQuery(commandBuffer, queryPool, slot, flags);
712843ec3f090ca979777b306abe7c25662b9429e06dChris Forbes
712943ec3f090ca979777b306abe7c25662b9429e06dChris Forbes    lock.lock();
713043ec3f090ca979777b306abe7c25662b9429e06dChris Forbes    if (pCB) {
713143ec3f090ca979777b306abe7c25662b9429e06dChris Forbes        QueryObject query = {queryPool, slot};
713243ec3f090ca979777b306abe7c25662b9429e06dChris Forbes        pCB->activeQueries.insert(query);
713343ec3f090ca979777b306abe7c25662b9429e06dChris Forbes        pCB->startedQueries.insert(query);
71349a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        addCommandBufferBinding(&GetQueryPoolNode(dev_data, queryPool)->cb_bindings,
71359b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                {HandleToUint64(queryPool), kVulkanObjectTypeQueryPool}, pCB);
71365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
71375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
71385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
713989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdEndQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t slot) {
7140946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski    bool skip = false;
714156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
7142ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
7143e17228238940d38a82570bc5b0ed4dd44e4cbd6dChris Forbes    QueryObject query = {queryPool, slot};
7144946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski    GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer);
7145946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski    if (cb_state) {
7146946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski        if (!cb_state->activeQueries.count(query)) {
7147df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
7148315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_1ae00652, "DS",
71499b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            "Ending a query before it was started: queryPool 0x%" PRIx64 ", index %d. %s",
7150315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(queryPool), slot, validation_error_map[VALIDATION_ERROR_1ae00652]);
71515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
7152baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt        skip |= ValidateCmdQueueFlags(dev_data, cb_state, "VkCmdEndQuery()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT,
7153315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                      VALIDATION_ERROR_1ae02415);
7154946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski        skip |= ValidateCmd(dev_data, cb_state, CMD_ENDQUERY, "VkCmdEndQuery()");
7155e17228238940d38a82570bc5b0ed4dd44e4cbd6dChris Forbes    }
7156e17228238940d38a82570bc5b0ed4dd44e4cbd6dChris Forbes    lock.unlock();
7157e17228238940d38a82570bc5b0ed4dd44e4cbd6dChris Forbes
7158e17228238940d38a82570bc5b0ed4dd44e4cbd6dChris Forbes    if (skip) return;
7159e17228238940d38a82570bc5b0ed4dd44e4cbd6dChris Forbes
7160e17228238940d38a82570bc5b0ed4dd44e4cbd6dChris Forbes    dev_data->dispatch_table.CmdEndQuery(commandBuffer, queryPool, slot);
7161e17228238940d38a82570bc5b0ed4dd44e4cbd6dChris Forbes
7162e17228238940d38a82570bc5b0ed4dd44e4cbd6dChris Forbes    lock.lock();
7163e17228238940d38a82570bc5b0ed4dd44e4cbd6dChris Forbes    if (cb_state) {
7164e17228238940d38a82570bc5b0ed4dd44e4cbd6dChris Forbes        cb_state->activeQueries.erase(query);
7165e17228238940d38a82570bc5b0ed4dd44e4cbd6dChris Forbes        cb_state->queryUpdates.emplace_back([=](VkQueue q){return setQueryState(q, commandBuffer, query, true);});
71669a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        addCommandBufferBinding(&GetQueryPoolNode(dev_data, queryPool)->cb_bindings,
71679b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                {HandleToUint64(queryPool), kVulkanObjectTypeQueryPool}, cb_state);
71685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
71695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
71705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
7171bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdResetQueryPool(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery,
7172bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                             uint32_t queryCount) {
7173946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski    bool skip = false;
717456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
7175ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
7176946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski    GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer);
71773a4c679ed508b10fd119bb97c127c79b5d126d74Chris Forbes        skip |= insideRenderPass(dev_data, cb_state, "vkCmdResetQueryPool()", VALIDATION_ERROR_1c600017);
71783a4c679ed508b10fd119bb97c127c79b5d126d74Chris Forbes        skip |= ValidateCmd(dev_data, cb_state, CMD_RESETQUERYPOOL, "VkCmdResetQueryPool()");
7179baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt        skip |= ValidateCmdQueueFlags(dev_data, cb_state, "VkCmdResetQueryPool()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT,
7180315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                      VALIDATION_ERROR_1c602415);
7181b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
71823a4c679ed508b10fd119bb97c127c79b5d126d74Chris Forbes
71833a4c679ed508b10fd119bb97c127c79b5d126d74Chris Forbes    if (skip) return;
71843a4c679ed508b10fd119bb97c127c79b5d126d74Chris Forbes
71853a4c679ed508b10fd119bb97c127c79b5d126d74Chris Forbes    dev_data->dispatch_table.CmdResetQueryPool(commandBuffer, queryPool, firstQuery, queryCount);
71863a4c679ed508b10fd119bb97c127c79b5d126d74Chris Forbes
71873a4c679ed508b10fd119bb97c127c79b5d126d74Chris Forbes    lock.lock();
71883a4c679ed508b10fd119bb97c127c79b5d126d74Chris Forbes    for (uint32_t i = 0; i < queryCount; i++) {
71893a4c679ed508b10fd119bb97c127c79b5d126d74Chris Forbes        QueryObject query = {queryPool, firstQuery + i};
71903a4c679ed508b10fd119bb97c127c79b5d126d74Chris Forbes        cb_state->waitedEventsBeforeQueryReset[query] = cb_state->waitedEvents;
7191f49bd2b5f4c968a3033b3e5099bbbcff51201575Chris Forbes        cb_state->queryUpdates.emplace_back([=](VkQueue q){return setQueryState(q, commandBuffer, query, false);});
71923a4c679ed508b10fd119bb97c127c79b5d126d74Chris Forbes    }
71933a4c679ed508b10fd119bb97c127c79b5d126d74Chris Forbes    addCommandBufferBinding(&GetQueryPoolNode(dev_data, queryPool)->cb_bindings,
71943a4c679ed508b10fd119bb97c127c79b5d126d74Chris Forbes                            {HandleToUint64(queryPool), kVulkanObjectTypeQueryPool}, cb_state);
71955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
71965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
71977ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbesstatic bool IsQueryInvalid(layer_data *dev_data, QUEUE_STATE *queue_data, VkQueryPool queryPool, uint32_t queryIndex) {
71987ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes    QueryObject query = {queryPool, queryIndex};
71997ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes    auto query_data = queue_data->queryToStateMap.find(query);
72007ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes    if (query_data != queue_data->queryToStateMap.end()) {
72017ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes        if (!query_data->second) return true;
72027ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes    } else {
72037ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes        auto it = dev_data->queryToStateMap.find(query);
72047ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes        if (it == dev_data->queryToStateMap.end() || !it->second)
72057ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes            return true;
72067ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes    }
72077ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes
72087ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes    return false;
72097ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes}
72107ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes
72117ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbesstatic bool validateQuery(VkQueue queue, GLOBAL_CB_NODE *pCB, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount) {
72123251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
721356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(pCB->commandBuffer), layer_data_map);
72147ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes    auto queue_data = GetQueueState(dev_data, queue);
72157ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes    if (!queue_data) return false;
7216d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine    for (uint32_t i = 0; i < queryCount; i++) {
72177ffbe89a37f5f822858a35646be0213fd2cd2b08Chris Forbes        if (IsQueryInvalid(dev_data, queue_data, queryPool, firstQuery + i)) {
72183251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
72199b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_QUERY, "DS",
72203251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "Requesting a copy from query to buffer with invalid query: queryPool 0x%" PRIx64 ", index %d",
72219b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(queryPool), firstQuery + i);
7222d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine        }
7223d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine    }
72243251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
7225d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine}
7226d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine
7227bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdCopyQueryPoolResults(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery,
7228bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                   uint32_t queryCount, VkBuffer dstBuffer, VkDeviceSize dstOffset,
7229bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                   VkDeviceSize stride, VkQueryResultFlags flags) {
7230946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski    bool skip = false;
723156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
7232ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
7233ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis
72349a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto cb_node = GetCBNode(dev_data, commandBuffer);
72359a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto dst_buff_state = GetBufferState(dev_data, dstBuffer);
72365cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis    if (cb_node && dst_buff_state) {
7237315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= ValidateMemoryIsBoundToBuffer(dev_data, dst_buff_state, "vkCmdCopyQueryPoolResults()", VALIDATION_ERROR_19400674);
7238ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis        // Validate that DST buffer has correct usage flags set
7239315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |=
7240315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis            ValidateBufferUsageFlags(dev_data, dst_buff_state, VK_BUFFER_USAGE_TRANSFER_DST_BIT, true, VALIDATION_ERROR_19400672,
7241315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                     "vkCmdCopyQueryPoolResults()", "VK_BUFFER_USAGE_TRANSFER_DST_BIT");
72424d285deca53ab503c0c9eb65ba1c4fb711138d7cChris Forbes        skip |= ValidateCmdQueueFlags(dev_data, cb_node, "vkCmdCopyQueryPoolResults()",
72434d285deca53ab503c0c9eb65ba1c4fb711138d7cChris Forbes                                      VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, VALIDATION_ERROR_19402415);
72444d285deca53ab503c0c9eb65ba1c4fb711138d7cChris Forbes        skip |= ValidateCmd(dev_data, cb_node, CMD_COPYQUERYPOOLRESULTS, "vkCmdCopyQueryPoolResults()");
72454d285deca53ab503c0c9eb65ba1c4fb711138d7cChris Forbes        skip |= insideRenderPass(dev_data, cb_node, "vkCmdCopyQueryPoolResults()", VALIDATION_ERROR_19400017);
72464d285deca53ab503c0c9eb65ba1c4fb711138d7cChris Forbes    }
72474d285deca53ab503c0c9eb65ba1c4fb711138d7cChris Forbes    lock.unlock();
72484d285deca53ab503c0c9eb65ba1c4fb711138d7cChris Forbes
72494d285deca53ab503c0c9eb65ba1c4fb711138d7cChris Forbes    if (skip) return;
72504d285deca53ab503c0c9eb65ba1c4fb711138d7cChris Forbes
72514d285deca53ab503c0c9eb65ba1c4fb711138d7cChris Forbes    dev_data->dispatch_table.CmdCopyQueryPoolResults(commandBuffer, queryPool, firstQuery, queryCount, dstBuffer, dstOffset,
72524d285deca53ab503c0c9eb65ba1c4fb711138d7cChris Forbes                                                     stride, flags);
72534d285deca53ab503c0c9eb65ba1c4fb711138d7cChris Forbes
72544d285deca53ab503c0c9eb65ba1c4fb711138d7cChris Forbes    lock.lock();
72554d285deca53ab503c0c9eb65ba1c4fb711138d7cChris Forbes    if (cb_node && dst_buff_state) {
72564d285deca53ab503c0c9eb65ba1c4fb711138d7cChris Forbes        AddCommandBufferBindingBuffer(dev_data, cb_node, dst_buff_state);
7257d807198f24437c1b2478ff1d06a33ce4873a1451Tobin Ehlis        cb_node->queue_submit_functions.emplace_back([=]() {
72585cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis            SetBufferMemoryValid(dev_data, dst_buff_state, true);
7259e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves            return false;
72604d285deca53ab503c0c9eb65ba1c4fb711138d7cChris Forbes        });
7261f49bd2b5f4c968a3033b3e5099bbbcff51201575Chris Forbes        cb_node->queryUpdates.emplace_back([=](VkQueue q) {
7262f49bd2b5f4c968a3033b3e5099bbbcff51201575Chris Forbes            return validateQuery(q, cb_node, queryPool, firstQuery, queryCount);
7263f49bd2b5f4c968a3033b3e5099bbbcff51201575Chris Forbes        });
72649a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        addCommandBufferBinding(&GetQueryPoolNode(dev_data, queryPool)->cb_bindings,
72659b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                {HandleToUint64(queryPool), kVulkanObjectTypeQueryPool}, cb_node);
72665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
72675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
72685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
7269bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdPushConstants(VkCommandBuffer commandBuffer, VkPipelineLayout layout, VkShaderStageFlags stageFlags,
7270bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                            uint32_t offset, uint32_t size, const void *pValues) {
7271946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski    bool skip = false;
727256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
7273ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
7274946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski    GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer);
7275946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski    if (cb_state) {
7276baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt        skip |= ValidateCmdQueueFlags(dev_data, cb_state, "vkCmdPushConstants()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT,
7277315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                      VALIDATION_ERROR_1bc02415);
7278946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski        skip |= ValidateCmd(dev_data, cb_state, CMD_PUSHCONSTANTS, "vkCmdPushConstants()");
72795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
7280946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski    skip |= validatePushConstantRange(dev_data, offset, size, "vkCmdPushConstants()");
72819e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz    if (0 == stageFlags) {
7282df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
7283315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_1bc2dc03, "DS",
7284315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        "vkCmdPushConstants() call has no stageFlags set. %s", validation_error_map[VALIDATION_ERROR_1bc2dc03]);
72859e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz    }
72869e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz
7287bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz    // Check if specified push constant range falls within a pipeline-defined range which has matching stageFlags.
7288bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz    // The spec doesn't seem to disallow having multiple push constant ranges with the
7289bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz    // same offset and size, but different stageFlags.  So we can't just check the
7290bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz    // stageFlags in the first range with matching offset and size.
7291bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz    if (!skip) {
7292bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz        const auto &ranges = getPipelineLayout(dev_data, layout)->push_constant_ranges;
7293bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz        bool found_matching_range = false;
7294bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz        for (const auto &range : ranges) {
7295bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz            if ((stageFlags == range.stageFlags) && (offset >= range.offset) && (offset + size <= range.offset + range.size)) {
7296bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz                found_matching_range = true;
729715a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis                break;
7298a95cb74c9d0947ab3821b15e1289755286ea78eeKarl Schultz            }
72999e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz        }
7300bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz        if (!found_matching_range) {
7301315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
7302315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_1bc002de, "DS",
7303315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            "vkCmdPushConstants() stageFlags = 0x%" PRIx32
7304315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            " do not match the stageFlags in any of the ranges with"
7305315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            " offset = %d and size = %d in pipeline layout 0x%" PRIx64 ". %s",
7306315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            (uint32_t)stageFlags, offset, size, HandleToUint64(layout),
7307315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            validation_error_map[VALIDATION_ERROR_1bc002de]);
730815a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis        }
73095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
7310b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
7311946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski    if (!skip) dev_data->dispatch_table.CmdPushConstants(commandBuffer, layout, stageFlags, offset, size, pValues);
73125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
73135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
7314bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdWriteTimestamp(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage,
7315bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                             VkQueryPool queryPool, uint32_t slot) {
7316946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski    bool skip = false;
731756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
7318ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
7319946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski    GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer);
7320946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski    if (cb_state) {
7321baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt        skip |= ValidateCmdQueueFlags(dev_data, cb_state, "vkCmdWriteTimestamp()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT,
7322315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                      VALIDATION_ERROR_1e802415);
7323946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski        skip |= ValidateCmd(dev_data, cb_state, CMD_WRITETIMESTAMP, "vkCmdWriteTimestamp()");
73245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
7325b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
73266eff586acc3c02decfb0c3af269693252efc8ef8Chris Forbes
73276eff586acc3c02decfb0c3af269693252efc8ef8Chris Forbes    if (skip) return;
73286eff586acc3c02decfb0c3af269693252efc8ef8Chris Forbes
73296eff586acc3c02decfb0c3af269693252efc8ef8Chris Forbes    dev_data->dispatch_table.CmdWriteTimestamp(commandBuffer, pipelineStage, queryPool, slot);
73306eff586acc3c02decfb0c3af269693252efc8ef8Chris Forbes
73316eff586acc3c02decfb0c3af269693252efc8ef8Chris Forbes    lock.lock();
73326eff586acc3c02decfb0c3af269693252efc8ef8Chris Forbes    if (cb_state) {
73336eff586acc3c02decfb0c3af269693252efc8ef8Chris Forbes        QueryObject query = {queryPool, slot};
73346eff586acc3c02decfb0c3af269693252efc8ef8Chris Forbes        cb_state->queryUpdates.emplace_back([=](VkQueue q) {return setQueryState(q, commandBuffer, query, true);});
73356eff586acc3c02decfb0c3af269693252efc8ef8Chris Forbes    }
73365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
73375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
73386600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinskistatic bool MatchUsage(layer_data *dev_data, uint32_t count, const VkAttachmentReference *attachments,
73399bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt                       const VkFramebufferCreateInfo *fbci, VkImageUsageFlagBits usage_flag,
73409bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt                       UNIQUE_VALIDATION_ERROR_CODE error_code) {
7341946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski    bool skip = false;
73426600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski
73436600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski    for (uint32_t attach = 0; attach < count; attach++) {
73446600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski        if (attachments[attach].attachment != VK_ATTACHMENT_UNUSED) {
73456600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski            // Attachment counts are verified elsewhere, but prevent an invalid access
73466600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski            if (attachments[attach].attachment < fbci->attachmentCount) {
73476600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski                const VkImageView *image_view = &fbci->pAttachments[attachments[attach].attachment];
73489a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                auto view_state = GetImageViewState(dev_data, *image_view);
734979fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis                if (view_state) {
73509a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                    const VkImageCreateInfo *ici = &GetImageState(dev_data, view_state->create_info.image)->createInfo;
73516600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski                    if (ici != nullptr) {
73526600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski                        if ((ici->usage & usage_flag) == 0) {
7353df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
7354df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                                            VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, error_code, "DS",
7355946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski                                            "vkCreateFramebuffer:  Framebuffer Attachment (%d) conflicts with the image's "
7356946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski                                            "IMAGE_USAGE flags (%s). %s",
7357946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski                                            attachments[attach].attachment, string_VkImageUsageFlagBits(usage_flag),
7358946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski                                            validation_error_map[error_code]);
73596600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski                        }
73606600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski                    }
73616600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski                }
73626600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski            }
73636600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski        }
73646600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski    }
7365946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski    return skip;
73666600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski}
73676600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski
7368d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis// Validate VkFramebufferCreateInfo which includes:
7369d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis// 1. attachmentCount equals renderPass attachmentCount
73705ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 2. corresponding framebuffer and renderpass attachments have matching formats
73715ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 3. corresponding framebuffer and renderpass attachments have matching sample counts
73725ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 4. fb attachments only have a single mip level
73735ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 5. fb attachment dimensions are each at least as large as the fb
73745ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 6. fb attachments use idenity swizzle
73755ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 7. fb attachments used by renderPass for color/input/ds have correct usage bit set
73766fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis// 8. fb dimensions are within physical device limits
7377d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlisstatic bool ValidateFramebufferCreateInfo(layer_data *dev_data, const VkFramebufferCreateInfo *pCreateInfo) {
73783251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
73796600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski
73809a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto rp_state = GetRenderPassState(dev_data, pCreateInfo->renderPass);
7381127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis    if (rp_state) {
7382127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis        const VkRenderPassCreateInfo *rpci = rp_state->createInfo.ptr();
7383d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis        if (rpci->attachmentCount != pCreateInfo->attachmentCount) {
73843251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(
7385d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis                dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT,
7386315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                HandleToUint64(pCreateInfo->renderPass), __LINE__, VALIDATION_ERROR_094006d8, "DS",
7387d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis                "vkCreateFramebuffer(): VkFramebufferCreateInfo attachmentCount of %u does not match attachmentCount of %u of "
73889bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt                "renderPass (0x%" PRIxLEAST64 ") being used to create Framebuffer. %s",
73899b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                pCreateInfo->attachmentCount, rpci->attachmentCount, HandleToUint64(pCreateInfo->renderPass),
7390315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                validation_error_map[VALIDATION_ERROR_094006d8]);
73915ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis        } else {
739241ebcb6b517b1de5ae456d46d866f5e84a96a2c5Tobin Ehlis            // attachmentCounts match, so make sure corresponding attachment details line up
73935ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis            const VkImageView *image_views = pCreateInfo->pAttachments;
73945ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis            for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) {
73959a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                auto view_state = GetImageViewState(dev_data, image_views[i]);
739612d5600c2f9e32343016fd944432ba95df370797Tobin Ehlis                auto &ivci = view_state->create_info;
739779fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis                if (ivci.format != rpci->pAttachments[i].format) {
73983251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= log_msg(
73995ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis                        dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT,
7400315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(pCreateInfo->renderPass), __LINE__, VALIDATION_ERROR_094006e0, "DS",
74019bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt                        "vkCreateFramebuffer(): VkFramebufferCreateInfo attachment #%u has format of %s that does not match "
74029bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt                        "the format of "
74039bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt                        "%s used by the corresponding attachment for renderPass (0x%" PRIxLEAST64 "). %s",
740479fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis                        i, string_VkFormat(ivci.format), string_VkFormat(rpci->pAttachments[i].format),
7405315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(pCreateInfo->renderPass), validation_error_map[VALIDATION_ERROR_094006e0]);
74065ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis                }
74079a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                const VkImageCreateInfo *ici = &GetImageState(dev_data, ivci.image)->createInfo;
74085ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis                if (ici->samples != rpci->pAttachments[i].samples) {
74093251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= log_msg(
741041ebcb6b517b1de5ae456d46d866f5e84a96a2c5Tobin Ehlis                        dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT,
7411315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(pCreateInfo->renderPass), __LINE__, VALIDATION_ERROR_094006e2, "DS",
74129bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt                        "vkCreateFramebuffer(): VkFramebufferCreateInfo attachment #%u has %s samples that do not match "
74139bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt                        "the %s samples used by the corresponding attachment for renderPass (0x%" PRIxLEAST64 "). %s",
741441ebcb6b517b1de5ae456d46d866f5e84a96a2c5Tobin Ehlis                        i, string_VkSampleCountFlagBits(ici->samples), string_VkSampleCountFlagBits(rpci->pAttachments[i].samples),
7415315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(pCreateInfo->renderPass), validation_error_map[VALIDATION_ERROR_094006e2]);
74165ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis                }
74175ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis                // Verify that view only has a single mip level
741879fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis                if (ivci.subresourceRange.levelCount != 1) {
74193251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT,
7420315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    0, __LINE__, VALIDATION_ERROR_094006e6, "DS",
74213251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    "vkCreateFramebuffer(): VkFramebufferCreateInfo attachment #%u has mip levelCount of %u "
74223251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    "but only a single mip level (levelCount ==  1) is allowed when creating a Framebuffer. %s",
7423315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    i, ivci.subresourceRange.levelCount, validation_error_map[VALIDATION_ERROR_094006e6]);
74245ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis                }
742579fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis                const uint32_t mip_level = ivci.subresourceRange.baseMipLevel;
7426aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis                uint32_t mip_width = max(1u, ici->extent.width >> mip_level);
7427aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis                uint32_t mip_height = max(1u, ici->extent.height >> mip_level);
742879fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis                if ((ivci.subresourceRange.layerCount < pCreateInfo->layers) || (mip_width < pCreateInfo->width) ||
7429aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis                    (mip_height < pCreateInfo->height)) {
74302c911c34092d685a7fa4630028f6fcf4bf80e349Cort Stratton                    skip |= log_msg(
74312c911c34092d685a7fa4630028f6fcf4bf80e349Cort Stratton                        dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
7432315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        VALIDATION_ERROR_094006e4, "DS",
74332c911c34092d685a7fa4630028f6fcf4bf80e349Cort Stratton                        "vkCreateFramebuffer(): VkFramebufferCreateInfo attachment #%u mip level %u has dimensions smaller "
74342c911c34092d685a7fa4630028f6fcf4bf80e349Cort Stratton                        "than the corresponding framebuffer dimensions. Here are the respective dimensions for attachment #%u, "
74352c911c34092d685a7fa4630028f6fcf4bf80e349Cort Stratton                        "framebuffer:\n"
74362c911c34092d685a7fa4630028f6fcf4bf80e349Cort Stratton                        "width: %u, %u\n"
74372c911c34092d685a7fa4630028f6fcf4bf80e349Cort Stratton                        "height: %u, %u\n"
74382c911c34092d685a7fa4630028f6fcf4bf80e349Cort Stratton                        "layerCount: %u, %u\n%s",
74392c911c34092d685a7fa4630028f6fcf4bf80e349Cort Stratton                        i, ivci.subresourceRange.baseMipLevel, i, mip_width, pCreateInfo->width, mip_height, pCreateInfo->height,
7440315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        ivci.subresourceRange.layerCount, pCreateInfo->layers, validation_error_map[VALIDATION_ERROR_094006e4]);
74415ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis                }
744279fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis                if (((ivci.components.r != VK_COMPONENT_SWIZZLE_IDENTITY) && (ivci.components.r != VK_COMPONENT_SWIZZLE_R)) ||
744379fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis                    ((ivci.components.g != VK_COMPONENT_SWIZZLE_IDENTITY) && (ivci.components.g != VK_COMPONENT_SWIZZLE_G)) ||
744479fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis                    ((ivci.components.b != VK_COMPONENT_SWIZZLE_IDENTITY) && (ivci.components.b != VK_COMPONENT_SWIZZLE_B)) ||
744579fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis                    ((ivci.components.a != VK_COMPONENT_SWIZZLE_IDENTITY) && (ivci.components.a != VK_COMPONENT_SWIZZLE_A))) {
74463251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= log_msg(
74475b9ab1fb8720c30edfbe8dd974e2364425471ad5Mark Lobodzinski                        dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
7448315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        VALIDATION_ERROR_094006e8, "DS",
7449da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis                        "vkCreateFramebuffer(): VkFramebufferCreateInfo attachment #%u has non-identy swizzle. All framebuffer "
7450da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis                        "attachments must have been created with the identity swizzle. Here are the actual swizzle values:\n"
7451da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis                        "r swizzle = %s\n"
7452da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis                        "g swizzle = %s\n"
7453da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis                        "b swizzle = %s\n"
74549bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt                        "a swizzle = %s\n"
74559bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt                        "%s",
745679fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis                        i, string_VkComponentSwizzle(ivci.components.r), string_VkComponentSwizzle(ivci.components.g),
74579bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt                        string_VkComponentSwizzle(ivci.components.b), string_VkComponentSwizzle(ivci.components.a),
7458315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_094006e8]);
74595ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis                }
74605ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis            }
7461d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis        }
74625ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis        // Verify correct attachment usage flags
74636600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski        for (uint32_t subpass = 0; subpass < rpci->subpassCount; subpass++) {
74646600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski            // Verify input attachments:
74653251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |=
74669bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt                MatchUsage(dev_data, rpci->pSubpasses[subpass].inputAttachmentCount, rpci->pSubpasses[subpass].pInputAttachments,
7467315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                           pCreateInfo, VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT, VALIDATION_ERROR_094006de);
74686600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski            // Verify color attachments:
74693251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |=
74709bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt                MatchUsage(dev_data, rpci->pSubpasses[subpass].colorAttachmentCount, rpci->pSubpasses[subpass].pColorAttachments,
7471315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                           pCreateInfo, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VALIDATION_ERROR_094006da);
74726600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski            // Verify depth/stencil attachments:
74736600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski            if (rpci->pSubpasses[subpass].pDepthStencilAttachment != nullptr) {
74743251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= MatchUsage(dev_data, 1, rpci->pSubpasses[subpass].pDepthStencilAttachment, pCreateInfo,
7475315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                   VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VALIDATION_ERROR_094006dc);
74766600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski            }
74776600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski        }
74786600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski    }
74796fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis    // Verify FB dimensions are within physical device limits
74809bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt    if (pCreateInfo->width > dev_data->phys_dev_properties.properties.limits.maxFramebufferWidth) {
74813251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
7482315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        VALIDATION_ERROR_094006ec, "DS",
74833251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "vkCreateFramebuffer(): Requested VkFramebufferCreateInfo width exceeds physical device limits. "
74843251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "Requested width: %u, device max: %u\n"
74853251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "%s",
74863251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        pCreateInfo->width, dev_data->phys_dev_properties.properties.limits.maxFramebufferWidth,
7487315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_094006ec]);
74889bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt    }
74899bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt    if (pCreateInfo->height > dev_data->phys_dev_properties.properties.limits.maxFramebufferHeight) {
74903251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
7491315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        VALIDATION_ERROR_094006f0, "DS",
74923251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "vkCreateFramebuffer(): Requested VkFramebufferCreateInfo height exceeds physical device limits. "
74933251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "Requested height: %u, device max: %u\n"
74943251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "%s",
74953251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        pCreateInfo->height, dev_data->phys_dev_properties.properties.limits.maxFramebufferHeight,
7496315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_094006f0]);
74979bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt    }
74989bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt    if (pCreateInfo->layers > dev_data->phys_dev_properties.properties.limits.maxFramebufferLayers) {
74993251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
7500315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        VALIDATION_ERROR_094006f4, "DS",
75013251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "vkCreateFramebuffer(): Requested VkFramebufferCreateInfo layers exceeds physical device limits. "
75023251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "Requested layers: %u, device max: %u\n"
75033251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "%s",
75043251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        pCreateInfo->layers, dev_data->phys_dev_properties.properties.limits.maxFramebufferLayers,
7505315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_094006f4]);
75066fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis    }
7507c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton    // Verify FB dimensions are greater than zero
7508c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton    if (pCreateInfo->width <= 0) {
7509c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
7510315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        VALIDATION_ERROR_094006ea, "DS",
7511c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton                        "vkCreateFramebuffer(): Requested VkFramebufferCreateInfo width must be greater than zero. %s",
7512315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_094006ea]);
7513c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton    }
7514c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton    if (pCreateInfo->height <= 0) {
7515c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
7516315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        VALIDATION_ERROR_094006ee, "DS",
7517c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton                        "vkCreateFramebuffer(): Requested VkFramebufferCreateInfo height must be greater than zero. %s",
7518315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_094006ee]);
7519c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton    }
7520c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton    if (pCreateInfo->layers <= 0) {
7521c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
7522315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        VALIDATION_ERROR_094006f2, "DS",
7523c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton                        "vkCreateFramebuffer(): Requested VkFramebufferCreateInfo layers must be greater than zero. %s",
7524315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_094006f2]);
7525c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton    }
75263251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
75276600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski}
75286600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski
752964c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis// Validate VkFramebufferCreateInfo state prior to calling down chain to create Framebuffer object
753064c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis//  Return true if an error is encountered and callback returns true to skip call down chain
753164c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis//   false indicates that call down chain should proceed
753264c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlisstatic bool PreCallValidateCreateFramebuffer(layer_data *dev_data, const VkFramebufferCreateInfo *pCreateInfo) {
753364c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis    // TODO : Verify that renderPass FB is created with is compatible with FB
75343251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
75353251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    skip |= ValidateFramebufferCreateInfo(dev_data, pCreateInfo);
75363251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
753764c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis}
753864c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis
753954e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis// CreateFramebuffer state has been validated and call down chain completed so record new framebuffer object
754054e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlisstatic void PostCallRecordCreateFramebuffer(layer_data *dev_data, const VkFramebufferCreateInfo *pCreateInfo, VkFramebuffer fb) {
754154e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis    // Shadow create info and store in map
7542c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis    std::unique_ptr<FRAMEBUFFER_STATE> fb_state(
7543ba9be0cec36d930fc0d5a0cbfbc00b0df49b08e4Tobin Ehlis        new FRAMEBUFFER_STATE(fb, pCreateInfo, GetRenderPassStateSharedPtr(dev_data, pCreateInfo->renderPass)));
754476f04ca0e692f9f15d5ef7e0c658c24d11f34ebcTobin Ehlis
754554e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis    for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) {
754654e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis        VkImageView view = pCreateInfo->pAttachments[i];
75479a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto view_state = GetImageViewState(dev_data, view);
754879fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis        if (!view_state) {
754954e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis            continue;
755054e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis        }
755154e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis        MT_FB_ATTACHMENT_INFO fb_info;
7552883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis        fb_info.view_state = view_state;
755379fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis        fb_info.image = view_state->create_info.image;
7554c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis        fb_state->attachments.push_back(fb_info);
755554e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis    }
7556c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis    dev_data->frameBufferMap[fb] = std::move(fb_state);
755754e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis}
755854e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis
755989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateFramebuffer(VkDevice device, const VkFramebufferCreateInfo *pCreateInfo,
7560bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                 const VkAllocationCallbacks *pAllocator, VkFramebuffer *pFramebuffer) {
756156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
7562ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
75633251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = PreCallValidateCreateFramebuffer(dev_data, pCreateInfo);
756464c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis    lock.unlock();
756564c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis
75663251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
756764c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis
75684a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.CreateFramebuffer(device, pCreateInfo, pAllocator, pFramebuffer);
75696600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski
75705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
757164c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis        lock.lock();
757254e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis        PostCallRecordCreateFramebuffer(dev_data, pCreateInfo, *pFramebuffer);
757354e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis        lock.unlock();
75745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
75755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
75765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
75775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
75784e11bb1277f55311686a42000520791e1db1dd7bbungemanstatic bool FindDependency(const uint32_t index, const uint32_t dependent, const std::vector<DAGNode> &subpass_to_node,
7579e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves                           std::unordered_set<uint32_t> &processed_nodes) {
75805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // If we have already checked this node we have not found a dependency path so return false.
7581cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (processed_nodes.count(index)) return false;
75825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    processed_nodes.insert(index);
75835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    const DAGNode &node = subpass_to_node[index];
75845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Look for a dependency path. If one exists return true else recurse on the previous nodes.
75854e11bb1277f55311686a42000520791e1db1dd7bbungeman    if (std::find(node.prev.begin(), node.prev.end(), dependent) == node.prev.end()) {
75865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (auto elem : node.prev) {
7587cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            if (FindDependency(elem, dependent, subpass_to_node, processed_nodes)) return true;
75885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
75895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    } else {
7590e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves        return true;
75915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
7592e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    return false;
75935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
75945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
75954e11bb1277f55311686a42000520791e1db1dd7bbungemanstatic bool CheckDependencyExists(const layer_data *dev_data, const uint32_t subpass,
75963251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                  const std::vector<uint32_t> &dependent_subpasses, const std::vector<DAGNode> &subpass_to_node,
75973251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                  bool &skip) {
7598e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool result = true;
75995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Loop through all subpasses that share the same attachment and make sure a dependency exists
76005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t k = 0; k < dependent_subpasses.size(); ++k) {
7601cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        if (static_cast<uint32_t>(subpass) == dependent_subpasses[k]) continue;
76025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        const DAGNode &node = subpass_to_node[subpass];
76035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // Check for a specified dependency between the two nodes. If one exists we are done.
76045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        auto prev_elem = std::find(node.prev.begin(), node.prev.end(), dependent_subpasses[k]);
76055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        auto next_elem = std::find(node.next.begin(), node.next.end(), dependent_subpasses[k]);
76065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (prev_elem == node.prev.end() && next_elem == node.next.end()) {
76077655cb8b5eb52badee0b011729a05afa36316d69Jan-Harald Fredriksen            // If no dependency exits an implicit dependency still might. If not, throw an error.
76085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            std::unordered_set<uint32_t> processed_nodes;
76097655cb8b5eb52badee0b011729a05afa36316d69Jan-Harald Fredriksen            if (!(FindDependency(subpass, dependent_subpasses[k], subpass_to_node, processed_nodes) ||
7610bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                  FindDependency(dependent_subpasses[k], subpass, subpass_to_node, processed_nodes))) {
76113251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
76123251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS",
76133251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "A dependency between subpasses %d and %d must exist but one is not specified.", subpass,
76143251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                dependent_subpasses[k]);
7615e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves                result = false;
76165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
76175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
76185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
76195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
76205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
76215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
76228860b85a52096f9f9b28616bc37feed505497a54Chris Forbesstatic bool CheckPreserved(const layer_data *dev_data, const VkRenderPassCreateInfo *pCreateInfo, const int index,
76233251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                           const uint32_t attachment, const std::vector<DAGNode> &subpass_to_node, int depth, bool &skip) {
76245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    const DAGNode &node = subpass_to_node[index];
76255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // If this node writes to the attachment return true as next nodes need to preserve the attachment.
76265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[index];
76275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) {
7628cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        if (attachment == subpass.pColorAttachments[j].attachment) return true;
76295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
7630a4ea781e8fff70c9db0bedad7fcb6bba08e35da7Tony Barbour    for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) {
7631a4ea781e8fff70c9db0bedad7fcb6bba08e35da7Tony Barbour        if (attachment == subpass.pInputAttachments[j].attachment) return true;
7632a4ea781e8fff70c9db0bedad7fcb6bba08e35da7Tony Barbour    }
76335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) {
7634cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        if (attachment == subpass.pDepthStencilAttachment->attachment) return true;
76355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
7636e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves    bool result = false;
76375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Loop through previous nodes and see if any of them write to the attachment.
76385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (auto elem : node.prev) {
76393251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        result |= CheckPreserved(dev_data, pCreateInfo, elem, attachment, subpass_to_node, depth + 1, skip);
76405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
76415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // If the attachment was written to by a previous node than this node needs to preserve it.
76425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (result && depth > 0) {
7643e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves        bool has_preserved = false;
76445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t j = 0; j < subpass.preserveAttachmentCount; ++j) {
76455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (subpass.pPreserveAttachments[j] == attachment) {
7646e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves                has_preserved = true;
76475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                break;
76485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
76495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
7650e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves        if (!has_preserved) {
76513251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
76523251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS",
76533251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "Attachment %d is used by a later subpass and must be preserved in subpass %d.", attachment, index);
76545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
76555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
76565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
76575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
76585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
7659cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskitemplate <class T>
7660cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskibool isRangeOverlapping(T offset1, T size1, T offset2, T size2) {
76615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return (((offset1 + size1) > offset2) && ((offset1 + size1) < (offset2 + size2))) ||
76625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis           ((offset1 > offset2) && (offset1 < (offset2 + size2)));
76635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
76645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
76655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisbool isRegionOverlapping(VkImageSubresourceRange range1, VkImageSubresourceRange range2) {
76665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return (isRangeOverlapping(range1.baseMipLevel, range1.levelCount, range2.baseMipLevel, range2.levelCount) &&
76675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            isRangeOverlapping(range1.baseArrayLayer, range1.layerCount, range2.baseArrayLayer, range2.layerCount));
76685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
76695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
7670c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlisstatic bool ValidateDependencies(const layer_data *dev_data, FRAMEBUFFER_STATE const *framebuffer,
7671127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis                                 RENDER_PASS_STATE const *renderPass) {
76723251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
7673fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes    auto const pFramebufferInfo = framebuffer->createInfo.ptr();
7674fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes    auto const pCreateInfo = renderPass->createInfo.ptr();
7675bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski    auto const &subpass_to_node = renderPass->subpassToNode;
76765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    std::vector<std::vector<uint32_t>> output_attachment_to_subpass(pCreateInfo->attachmentCount);
76775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    std::vector<std::vector<uint32_t>> input_attachment_to_subpass(pCreateInfo->attachmentCount);
76785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    std::vector<std::vector<uint32_t>> overlapping_attachments(pCreateInfo->attachmentCount);
76795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Find overlapping attachments
76805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) {
76815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t j = i + 1; j < pCreateInfo->attachmentCount; ++j) {
76825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            VkImageView viewi = pFramebufferInfo->pAttachments[i];
76835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            VkImageView viewj = pFramebufferInfo->pAttachments[j];
76845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (viewi == viewj) {
76855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                overlapping_attachments[i].push_back(j);
76865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                overlapping_attachments[j].push_back(i);
76875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                continue;
76885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
76899a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            auto view_state_i = GetImageViewState(dev_data, viewi);
76909a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            auto view_state_j = GetImageViewState(dev_data, viewj);
769179fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis            if (!view_state_i || !view_state_j) {
76925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                continue;
76935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
769479fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis            auto view_ci_i = view_state_i->create_info;
769579fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis            auto view_ci_j = view_state_j->create_info;
769679fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis            if (view_ci_i.image == view_ci_j.image && isRegionOverlapping(view_ci_i.subresourceRange, view_ci_j.subresourceRange)) {
76975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                overlapping_attachments[i].push_back(j);
76985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                overlapping_attachments[j].push_back(i);
76995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                continue;
77005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
77019a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            auto image_data_i = GetImageState(dev_data, view_ci_i.image);
77029a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            auto image_data_j = GetImageState(dev_data, view_ci_j.image);
77036d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis            if (!image_data_i || !image_data_j) {
77045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                continue;
77055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
7706e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis            if (image_data_i->binding.mem == image_data_j->binding.mem &&
7707e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis                isRangeOverlapping(image_data_i->binding.offset, image_data_i->binding.size, image_data_j->binding.offset,
7708e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis                                   image_data_j->binding.size)) {
77095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                overlapping_attachments[i].push_back(j);
77105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                overlapping_attachments[j].push_back(i);
77115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
77125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
77135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
77145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < overlapping_attachments.size(); ++i) {
77155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        uint32_t attachment = i;
77165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (auto other_attachment : overlapping_attachments[i]) {
77175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (!(pCreateInfo->pAttachments[attachment].flags & VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT)) {
77189b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT,
7719315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                HandleToUint64(framebuffer->framebuffer), __LINE__, VALIDATION_ERROR_12200682, "DS",
77209b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                "Attachment %d aliases attachment %d but doesn't "
77219b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                "set VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT. %s",
7722315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                attachment, other_attachment, validation_error_map[VALIDATION_ERROR_12200682]);
77235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
77245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (!(pCreateInfo->pAttachments[other_attachment].flags & VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT)) {
77259b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT,
7726315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                HandleToUint64(framebuffer->framebuffer), __LINE__, VALIDATION_ERROR_12200682, "DS",
77279b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                "Attachment %d aliases attachment %d but doesn't "
77289b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                "set VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT. %s",
7729315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                other_attachment, attachment, validation_error_map[VALIDATION_ERROR_12200682]);
77305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
77315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
77325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
77335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Find for each attachment the subpasses that use them.
77341c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young    unordered_set<uint32_t> attachmentIndices;
77355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) {
77365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i];
77371c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young        attachmentIndices.clear();
77385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) {
77395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            uint32_t attachment = subpass.pInputAttachments[j].attachment;
7740cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            if (attachment == VK_ATTACHMENT_UNUSED) continue;
77415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            input_attachment_to_subpass[attachment].push_back(i);
77425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            for (auto overlapping_attachment : overlapping_attachments[attachment]) {
77435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                input_attachment_to_subpass[overlapping_attachment].push_back(i);
77445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
77455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
77465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) {
77475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            uint32_t attachment = subpass.pColorAttachments[j].attachment;
7748cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            if (attachment == VK_ATTACHMENT_UNUSED) continue;
77495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            output_attachment_to_subpass[attachment].push_back(i);
77505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            for (auto overlapping_attachment : overlapping_attachments[attachment]) {
77515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                output_attachment_to_subpass[overlapping_attachment].push_back(i);
77525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
77531c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young            attachmentIndices.insert(attachment);
77545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
77555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) {
77565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            uint32_t attachment = subpass.pDepthStencilAttachment->attachment;
77575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            output_attachment_to_subpass[attachment].push_back(i);
77585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            for (auto overlapping_attachment : overlapping_attachments[attachment]) {
77595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                output_attachment_to_subpass[overlapping_attachment].push_back(i);
77605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
77611c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young
77621c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young            if (attachmentIndices.count(attachment)) {
77633251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |=
7764df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
7765df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                            __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS",
77668860b85a52096f9f9b28616bc37feed505497a54Chris Forbes                            "Cannot use same attachment (%u) as both color and depth output in same subpass (%u).", attachment, i);
77671c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young            }
77685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
77695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
77705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // If there is a dependency needed make sure one exists
77715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) {
77725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i];
77735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // If the attachment is an input then all subpasses that output must have a dependency relationship
77745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) {
777593fe72ec8460857bdb3c101095e6eb96d6171341Chris Forbes            uint32_t attachment = subpass.pInputAttachments[j].attachment;
7776cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            if (attachment == VK_ATTACHMENT_UNUSED) continue;
77773251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            CheckDependencyExists(dev_data, i, output_attachment_to_subpass[attachment], subpass_to_node, skip);
77785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
77795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // If the attachment is an output then all subpasses that use the attachment must have a dependency relationship
77805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) {
778193fe72ec8460857bdb3c101095e6eb96d6171341Chris Forbes            uint32_t attachment = subpass.pColorAttachments[j].attachment;
7782cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            if (attachment == VK_ATTACHMENT_UNUSED) continue;
77833251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            CheckDependencyExists(dev_data, i, output_attachment_to_subpass[attachment], subpass_to_node, skip);
77843251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            CheckDependencyExists(dev_data, i, input_attachment_to_subpass[attachment], subpass_to_node, skip);
77855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
77865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) {
77875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            const uint32_t &attachment = subpass.pDepthStencilAttachment->attachment;
77883251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            CheckDependencyExists(dev_data, i, output_attachment_to_subpass[attachment], subpass_to_node, skip);
77893251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            CheckDependencyExists(dev_data, i, input_attachment_to_subpass[attachment], subpass_to_node, skip);
77905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
77915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
77925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // Loop through implicit dependencies, if this pass reads make sure the attachment is preserved for all passes after it was
77935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    // written.
77945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) {
77955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i];
77965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) {
77973251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            CheckPreserved(dev_data, pCreateInfo, i, subpass.pInputAttachments[j].attachment, subpass_to_node, 0, skip);
77985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
77995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
78003251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
78015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
78025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
780332f68580aa01aab3e923cb52915a1d3dd4e993c5Chris Forbesstatic bool CreatePassDAG(const layer_data *dev_data, const VkRenderPassCreateInfo *pCreateInfo,
7804ea0a13226a513846fe5a7009783c5536b1255a56Tobin Ehlis                          std::vector<DAGNode> &subpass_to_node, std::vector<bool> &has_self_dependency,
7805ea0a13226a513846fe5a7009783c5536b1255a56Tobin Ehlis                          std::vector<int32_t> &subpass_to_dep_index) {
78063251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
78075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) {
78085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        DAGNode &subpass_node = subpass_to_node[i];
78095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        subpass_node.pass = i;
7810ea0a13226a513846fe5a7009783c5536b1255a56Tobin Ehlis        subpass_to_dep_index[i] = -1;  // Default to no dependency and overwrite below as needed
78115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
78125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < pCreateInfo->dependencyCount; ++i) {
78135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        const VkSubpassDependency &dependency = pCreateInfo->pDependencies[i];
781466a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes        if (dependency.srcSubpass == VK_SUBPASS_EXTERNAL || dependency.dstSubpass == VK_SUBPASS_EXTERNAL) {
781566a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes            if (dependency.srcSubpass == dependency.dstSubpass) {
78163251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |=
7817df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
7818df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                            __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS", "The src and dest subpasses cannot both be external.");
781966a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes            }
782066a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes        } else if (dependency.srcSubpass > dependency.dstSubpass) {
78213251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
78223251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS",
7823ea0a13226a513846fe5a7009783c5536b1255a56Tobin Ehlis                            "Dependency graph must be specified such that an earlier pass cannot depend on a later pass.");
78245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        } else if (dependency.srcSubpass == dependency.dstSubpass) {
78255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            has_self_dependency[dependency.srcSubpass] = true;
7826b6820dcebf864c3e157647317ddd26180309fc2bChris Forbes            subpass_to_dep_index[dependency.srcSubpass] = i;
78275c6aacf95832467d52b2fde1130b04bef559573aChris Forbes        } else {
78285c6aacf95832467d52b2fde1130b04bef559573aChris Forbes            subpass_to_node[dependency.dstSubpass].prev.push_back(dependency.srcSubpass);
78295c6aacf95832467d52b2fde1130b04bef559573aChris Forbes            subpass_to_node[dependency.srcSubpass].next.push_back(dependency.dstSubpass);
78305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
78315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
78323251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
78335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
7834918c283ac4f8c604b79abd0c8b5706d2a7352a34Chris Forbes
783589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo *pCreateInfo,
7836bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                  const VkAllocationCallbacks *pAllocator, VkShaderModule *pShaderModule) {
783756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
78387aec8a354c8de254cab09f6da7f24a794525d31eChris Forbes    bool spirv_valid;
7839b1f65702539fd041337fccd493dc6d38dd2a603eChris Forbes
78407aec8a354c8de254cab09f6da7f24a794525d31eChris Forbes    if (PreCallValidateCreateShaderModule(dev_data, pCreateInfo, &spirv_valid))
78417aec8a354c8de254cab09f6da7f24a794525d31eChris Forbes        return VK_ERROR_VALIDATION_FAILED_EXT;
78425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
78434a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult res = dev_data->dispatch_table.CreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
78445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
784559ae0ccadec962d9ca2cce7584fad6c57c1a4458Tobin Ehlis    if (res == VK_SUCCESS) {
7846ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes        lock_guard_t lock(global_lock);
78477aec8a354c8de254cab09f6da7f24a794525d31eChris Forbes        unique_ptr<shader_module> new_shader_module(spirv_valid ? new shader_module(pCreateInfo) : new shader_module());
78487aec8a354c8de254cab09f6da7f24a794525d31eChris Forbes        dev_data->shaderModuleMap[*pShaderModule] = std::move(new_shader_module);
78495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
78505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return res;
78515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
78525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
78534f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinskistatic bool ValidateAttachmentIndex(layer_data *dev_data, uint32_t attachment, uint32_t attachment_count, const char *type) {
78543251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
78554f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski    if (attachment >= attachment_count && attachment != VK_ATTACHMENT_UNUSED) {
78563251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
7857315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        VALIDATION_ERROR_12200684, "DS",
78583251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "CreateRenderPass: %s attachment %d must be less than the total number of attachments %d. %s", type,
7859315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        attachment, attachment_count, validation_error_map[VALIDATION_ERROR_12200684]);
78604f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski    }
78613251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
78624f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski}
78634f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski
7864bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic bool IsPowerOfTwo(unsigned x) { return x && !(x & (x - 1)); }
7865805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes
78664f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinskistatic bool ValidateRenderpassAttachmentUsage(layer_data *dev_data, const VkRenderPassCreateInfo *pCreateInfo) {
78673251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
78684f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski    for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) {
78694f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i];
78704f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        if (subpass.pipelineBindPoint != VK_PIPELINE_BIND_POINT_GRAPHICS) {
78713251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
7872315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            __LINE__, VALIDATION_ERROR_14000698, "DS",
78733251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "CreateRenderPass: Pipeline bind point for subpass %d must be VK_PIPELINE_BIND_POINT_GRAPHICS. %s", i,
7874315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            validation_error_map[VALIDATION_ERROR_14000698]);
78754f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        }
7876ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton
78774f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        for (uint32_t j = 0; j < subpass.preserveAttachmentCount; ++j) {
78784f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski            uint32_t attachment = subpass.pPreserveAttachments[j];
78794f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski            if (attachment == VK_ATTACHMENT_UNUSED) {
78803251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
7881315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                __LINE__, VALIDATION_ERROR_140006aa, "DS",
78823251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "CreateRenderPass:  Preserve attachment (%d) must not be VK_ATTACHMENT_UNUSED. %s", j,
7883315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                validation_error_map[VALIDATION_ERROR_140006aa]);
78844f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski            } else {
78853251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= ValidateAttachmentIndex(dev_data, attachment, pCreateInfo->attachmentCount, "Preserve");
7886ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton
7887ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                bool found = (subpass.pDepthStencilAttachment != NULL && subpass.pDepthStencilAttachment->attachment == attachment);
7888ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                for (uint32_t r = 0; !found && r < subpass.inputAttachmentCount; ++r) {
7889ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                    found = (subpass.pInputAttachments[r].attachment == attachment);
7890ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                }
7891ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                for (uint32_t r = 0; !found && r < subpass.colorAttachmentCount; ++r) {
7892ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                    found = (subpass.pColorAttachments[r].attachment == attachment) ||
7893ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                            (subpass.pResolveAttachments != NULL && subpass.pResolveAttachments[r].attachment == attachment);
7894ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                }
7895ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                if (found) {
7896ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                    skip |= log_msg(
7897ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                        dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
7898315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        VALIDATION_ERROR_140006ac, "DS",
7899ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                        "CreateRenderPass: subpass %u pPreserveAttachments[%u] (%u) must not be used elsewhere in the subpass. %s",
7900315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        i, j, attachment, validation_error_map[VALIDATION_ERROR_140006ac]);
7901ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                }
79024f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski            }
79034f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        }
79046a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes
7905bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        auto subpass_performs_resolve =
7906bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski            subpass.pResolveAttachments &&
7907bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski            std::any_of(subpass.pResolveAttachments, subpass.pResolveAttachments + subpass.colorAttachmentCount,
7908bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                        [](VkAttachmentReference ref) { return ref.attachment != VK_ATTACHMENT_UNUSED; });
79096a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes
7910805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes        unsigned sample_count = 0;
7911805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes
79124f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) {
79134f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski            uint32_t attachment;
79144f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski            if (subpass.pResolveAttachments) {
79154f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski                attachment = subpass.pResolveAttachments[j].attachment;
79163251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= ValidateAttachmentIndex(dev_data, attachment, pCreateInfo->attachmentCount, "Resolve");
79176a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes
79183251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                if (!skip && attachment != VK_ATTACHMENT_UNUSED &&
79196a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes                    pCreateInfo->pAttachments[attachment].samples != VK_SAMPLE_COUNT_1_BIT) {
79203251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT,
7921315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    0, __LINE__, VALIDATION_ERROR_140006a2, "DS",
79223251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    "CreateRenderPass:  Subpass %u requests multisample resolve into attachment %u, "
79233251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    "which must have VK_SAMPLE_COUNT_1_BIT but has %s. %s",
79243251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    i, attachment, string_VkSampleCountFlagBits(pCreateInfo->pAttachments[attachment].samples),
7925315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    validation_error_map[VALIDATION_ERROR_140006a2]);
79266a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes                }
7927ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton
7928ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                if (!skip && subpass.pResolveAttachments[j].attachment != VK_ATTACHMENT_UNUSED &&
7929ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                    subpass.pColorAttachments[j].attachment == VK_ATTACHMENT_UNUSED) {
7930ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                    skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT,
7931315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    0, __LINE__, VALIDATION_ERROR_1400069e, "DS",
7932ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                                    "CreateRenderPass:  Subpass %u requests multisample resolve from attachment %u "
7933ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                                    "which has attachment=VK_ATTACHMENT_UNUSED. %s",
7934315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    i, attachment, validation_error_map[VALIDATION_ERROR_1400069e]);
7935ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                }
79364f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski            }
79374f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski            attachment = subpass.pColorAttachments[j].attachment;
79383251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= ValidateAttachmentIndex(dev_data, attachment, pCreateInfo->attachmentCount, "Color");
79396a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes
79403251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            if (!skip && attachment != VK_ATTACHMENT_UNUSED) {
7941805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes                sample_count |= (unsigned)pCreateInfo->pAttachments[attachment].samples;
7942805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes
7943bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                if (subpass_performs_resolve && pCreateInfo->pAttachments[attachment].samples == VK_SAMPLE_COUNT_1_BIT) {
79443251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT,
7945315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    0, __LINE__, VALIDATION_ERROR_140006a0, "DS",
79463251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    "CreateRenderPass:  Subpass %u requests multisample resolve from attachment %u "
79473251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    "which has VK_SAMPLE_COUNT_1_BIT. %s",
7948315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    i, attachment, validation_error_map[VALIDATION_ERROR_140006a0]);
7949dc7c45f01ae5690f7c969b4760463c1a6bac52d5Chris Forbes                }
7950ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton
7951ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                if (subpass_performs_resolve && subpass.pResolveAttachments[j].attachment != VK_ATTACHMENT_UNUSED) {
7952ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                    const auto &color_desc = pCreateInfo->pAttachments[attachment];
7953ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                    const auto &resolve_desc = pCreateInfo->pAttachments[subpass.pResolveAttachments[j].attachment];
7954ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                    if (color_desc.format != resolve_desc.format) {
7955315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        skip |=
7956315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT,
7957315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    0, __LINE__, VALIDATION_ERROR_140006a4, "DS",
7958315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    "CreateRenderPass:  Subpass %u pColorAttachments[%u] resolves to an attachment with a "
7959315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    "different format. "
7960315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    "color format: %u, resolve format: %u. %s",
7961315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    i, j, color_desc.format, resolve_desc.format, validation_error_map[VALIDATION_ERROR_140006a4]);
7962ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                    }
7963ce7bf009f8fc7e268efdc76ba61e3491d290ebd9Cort Stratton                }
7964497e33d6b0547f5dccca245a5b6777831fbb0de0Maciej Jesionowski
7965497e33d6b0547f5dccca245a5b6777831fbb0de0Maciej Jesionowski                if (dev_data->extensions.vk_amd_mixed_attachment_samples &&
7966497e33d6b0547f5dccca245a5b6777831fbb0de0Maciej Jesionowski                    subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) {
7967497e33d6b0547f5dccca245a5b6777831fbb0de0Maciej Jesionowski                    const auto depth_stencil_sample_count = pCreateInfo->pAttachments[subpass.pDepthStencilAttachment->attachment].samples;
7968497e33d6b0547f5dccca245a5b6777831fbb0de0Maciej Jesionowski                    if (pCreateInfo->pAttachments[attachment].samples > depth_stencil_sample_count) {
7969497e33d6b0547f5dccca245a5b6777831fbb0de0Maciej Jesionowski                        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
7970497e33d6b0547f5dccca245a5b6777831fbb0de0Maciej Jesionowski                                        __LINE__, VALIDATION_ERROR_14000bc4, "DS",
7971497e33d6b0547f5dccca245a5b6777831fbb0de0Maciej Jesionowski                                        "CreateRenderPass:  Subpass %u pColorAttachments[%u] has %s which is larger than "
7972497e33d6b0547f5dccca245a5b6777831fbb0de0Maciej Jesionowski                                        "depth/stencil attachment %s. %s",
7973497e33d6b0547f5dccca245a5b6777831fbb0de0Maciej Jesionowski                                        i, j, string_VkSampleCountFlagBits(pCreateInfo->pAttachments[attachment].samples),
7974497e33d6b0547f5dccca245a5b6777831fbb0de0Maciej Jesionowski                                        string_VkSampleCountFlagBits(depth_stencil_sample_count), validation_error_map[VALIDATION_ERROR_14000bc4]);
7975497e33d6b0547f5dccca245a5b6777831fbb0de0Maciej Jesionowski                    }
7976497e33d6b0547f5dccca245a5b6777831fbb0de0Maciej Jesionowski                }
79776a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes            }
79784f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        }
7979dc7c45f01ae5690f7c969b4760463c1a6bac52d5Chris Forbes
79804f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) {
79814f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski            uint32_t attachment = subpass.pDepthStencilAttachment->attachment;
79823251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= ValidateAttachmentIndex(dev_data, attachment, pCreateInfo->attachmentCount, "Depth stencil");
7983805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes
79843251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            if (!skip && attachment != VK_ATTACHMENT_UNUSED) {
7985805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes                sample_count |= (unsigned)pCreateInfo->pAttachments[attachment].samples;
7986805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes            }
79874f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        }
7988dc7c45f01ae5690f7c969b4760463c1a6bac52d5Chris Forbes
79894f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) {
79904f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski            uint32_t attachment = subpass.pInputAttachments[j].attachment;
79913251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= ValidateAttachmentIndex(dev_data, attachment, pCreateInfo->attachmentCount, "Input");
79924f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        }
7993805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes
7994497e33d6b0547f5dccca245a5b6777831fbb0de0Maciej Jesionowski        if (!dev_data->extensions.vk_amd_mixed_attachment_samples &&
7995497e33d6b0547f5dccca245a5b6777831fbb0de0Maciej Jesionowski            sample_count && !IsPowerOfTwo(sample_count)) {
79963251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
7997315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            __LINE__, VALIDATION_ERROR_0082b401, "DS",
79983251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "CreateRenderPass:  Subpass %u attempts to render to "
79993251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "attachments with inconsistent sample counts. %s",
8000315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            i, validation_error_map[VALIDATION_ERROR_0082b401]);
8001805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes        }
80024f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski    }
80033251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
80044f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski}
80054f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski
80065245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbesstatic void MarkAttachmentFirstUse(RENDER_PASS_STATE *render_pass,
80075245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes                                   uint32_t index,
80085245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes                                   bool is_read) {
80095245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes    if (index == VK_ATTACHMENT_UNUSED)
80105245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes        return;
80115245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes
80125245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes    if (!render_pass->attachment_first_read.count(index))
80135245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes        render_pass->attachment_first_read[index] = is_read;
80145245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes}
80155245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes
801689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateRenderPass(VkDevice device, const VkRenderPassCreateInfo *pCreateInfo,
80174f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski                                                const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass) {
80183251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
801956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
80204f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski
8021ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
80224f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski    // TODO: As part of wrapping up the mem_tracker/core_validation merge the following routine should be consolidated with
80234f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski    //       ValidateLayouts.
80243251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    skip |= ValidateRenderpassAttachmentUsage(dev_data, pCreateInfo);
8025208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis    for (uint32_t i = 0; i < pCreateInfo->dependencyCount; ++i) {
80263251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateStageMaskGsTsEnables(dev_data, pCreateInfo->pDependencies[i].srcStageMask, "vkCreateRenderPass()",
8027315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                             VALIDATION_ERROR_13e006b8, VALIDATION_ERROR_13e006bc);
80283251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateStageMaskGsTsEnables(dev_data, pCreateInfo->pDependencies[i].dstStageMask, "vkCreateRenderPass()",
8029315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                             VALIDATION_ERROR_13e006ba, VALIDATION_ERROR_13e006be);
8030208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis    }
80313251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (!skip) {
80323251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateLayouts(dev_data, device, pCreateInfo);
8033ab38df28c5ae1816c5fa33c0c7840c6950e83f0dChris Forbes    }
8034ff6101de02d1677fb54962e2ff57875e76898e26Chris Forbes    lock.unlock();
80354f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski
80363251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (skip) {
80374f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        return VK_ERROR_VALIDATION_FAILED_EXT;
80384f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski    }
80394f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski
80404a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.CreateRenderPass(device, pCreateInfo, pAllocator, pRenderPass);
8041ff6101de02d1677fb54962e2ff57875e76898e26Chris Forbes
80425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
80434f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        lock.lock();
80444f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski
80454f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        std::vector<bool> has_self_dependency(pCreateInfo->subpassCount);
80464f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski        std::vector<DAGNode> subpass_to_node(pCreateInfo->subpassCount);
8047ea0a13226a513846fe5a7009783c5536b1255a56Tobin Ehlis        std::vector<int32_t> subpass_to_dep_index(pCreateInfo->subpassCount);
8048ea0a13226a513846fe5a7009783c5536b1255a56Tobin Ehlis        skip |= CreatePassDAG(dev_data, pCreateInfo, subpass_to_node, has_self_dependency, subpass_to_dep_index);
80494f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski
8050e6852f66a1f1eb57097dbf98b8218104849fda0fTobin Ehlis        auto render_pass = std::make_shared<RENDER_PASS_STATE>(pCreateInfo);
805198cddf7090b5d5dcc382045867753ef703d1c3d3Chris Forbes        render_pass->renderPass = *pRenderPass;
8052cf2686cdbb12af8a29ca598c126b5e37215f0ef7Chris Forbes        render_pass->hasSelfDependency = has_self_dependency;
8053cf2686cdbb12af8a29ca598c126b5e37215f0ef7Chris Forbes        render_pass->subpassToNode = subpass_to_node;
8054ea0a13226a513846fe5a7009783c5536b1255a56Tobin Ehlis        render_pass->subpass_to_dependency_index = subpass_to_dep_index;
8055db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes
805687e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis        for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) {
805787e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis            const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i];
805887e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis            for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) {
80595245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes                MarkAttachmentFirstUse(render_pass.get(), subpass.pColorAttachments[j].attachment, false);
80609cde292b1c19c643b7c13018d9834cccfe6ef7eaChris Forbes
80615245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes                // resolve attachments are considered to be written
80625245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes                if (subpass.pResolveAttachments) {
80635245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes                    MarkAttachmentFirstUse(render_pass.get(), subpass.pResolveAttachments[j].attachment, false);
80649cde292b1c19c643b7c13018d9834cccfe6ef7eaChris Forbes                }
806587e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis            }
80665245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes            if (subpass.pDepthStencilAttachment) {
80675245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes                MarkAttachmentFirstUse(render_pass.get(), subpass.pDepthStencilAttachment->attachment, false);
806887e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis            }
8069a5ce96d7c88653668a2b33a6b72bd3cb16d73f48Michael Lentine            for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) {
80705245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes                MarkAttachmentFirstUse(render_pass.get(), subpass.pInputAttachments[j].attachment, true);
8071a5ce96d7c88653668a2b33a6b72bd3cb16d73f48Michael Lentine            }
807287e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis        }
8073db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes
8074fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes        dev_data->renderPassMap[*pRenderPass] = std::move(render_pass);
80755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
80765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
80775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
80784f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski
8079eb4c61477130f69f48fdf3ac31cb82104181cc73Chris Forbesstatic bool validatePrimaryCommandBuffer(const layer_data *dev_data, const GLOBAL_CB_NODE *pCB, char const *cmd_name,
80809bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt                                         UNIQUE_VALIDATION_ERROR_CODE error_code) {
80813251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
80825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB->createInfo.level != VK_COMMAND_BUFFER_LEVEL_PRIMARY) {
80833251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
80849b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        HandleToUint64(pCB->commandBuffer), __LINE__, error_code, "DS",
80859b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        "Cannot execute command %s on a secondary command buffer. %s", cmd_name, validation_error_map[error_code]);
80865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
80873251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
80885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
80895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
80908860b85a52096f9f9b28616bc37feed505497a54Chris Forbesstatic bool VerifyRenderAreaBounds(const layer_data *dev_data, const VkRenderPassBeginInfo *pRenderPassBegin) {
80913251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
8092c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis    const safe_VkFramebufferCreateInfo *pFramebufferInfo =
80939a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        &GetFramebufferState(dev_data, pRenderPassBegin->framebuffer)->createInfo;
8094885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine    if (pRenderPassBegin->renderArea.offset.x < 0 ||
8095885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine        (pRenderPassBegin->renderArea.offset.x + pRenderPassBegin->renderArea.extent.width) > pFramebufferInfo->width ||
8096885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine        pRenderPassBegin->renderArea.offset.y < 0 ||
8097885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine        (pRenderPassBegin->renderArea.offset.y + pRenderPassBegin->renderArea.extent.height) > pFramebufferInfo->height) {
80983251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= static_cast<bool>(log_msg(
8099df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski            dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
8100885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine            DRAWSTATE_INVALID_RENDER_AREA, "CORE",
8101885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine            "Cannot execute a render pass with renderArea not within the bound of the "
8102885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine            "framebuffer. RenderArea: x %d, y %d, width %d, height %d. Framebuffer: width %d, "
8103885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine            "height %d.",
8104885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine            pRenderPassBegin->renderArea.offset.x, pRenderPassBegin->renderArea.offset.y, pRenderPassBegin->renderArea.extent.width,
8105885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine            pRenderPassBegin->renderArea.extent.height, pFramebufferInfo->width, pFramebufferInfo->height));
8106885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine    }
81073251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
8108885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine}
8109885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine
81101a65650f856376768d7b03ea2d080aaff87cacfdMark 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
81111a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski// [load|store]Op flag must be checked
81121a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski// TODO: The memory valid flag in DEVICE_MEM_INFO should probably be split to track the validity of stencil memory separately.
8113cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskitemplate <typename T>
8114cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskistatic bool FormatSpecificLoadAndStoreOpSettings(VkFormat format, T color_depth_op, T stencil_op, T op) {
8115a49b8a211ce07e7fa2225d23f8cb11f1055b418aMark Lobodzinski    if (color_depth_op != op && stencil_op != op) {
8116a49b8a211ce07e7fa2225d23f8cb11f1055b418aMark Lobodzinski        return false;
8117a49b8a211ce07e7fa2225d23f8cb11f1055b418aMark Lobodzinski    }
811816769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton    bool check_color_depth_load_op = !FormatIsStencilOnly(format);
811916769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton    bool check_stencil_load_op = FormatIsDepthAndStencil(format) || !check_color_depth_load_op;
8120a49b8a211ce07e7fa2225d23f8cb11f1055b418aMark Lobodzinski
81210d9453d85335963d6cabfbf400b058dc905ea238Chris Forbes    return ((check_color_depth_load_op && (color_depth_op == op)) ||
81220d9453d85335963d6cabfbf400b058dc905ea238Chris Forbes            (check_stencil_load_op && (stencil_op == op)));
81231a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski}
81241a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski
8125bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBeginRenderPass(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *pRenderPassBegin,
8126bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                              VkSubpassContents contents) {
81273251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
812856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
8129ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
81309a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *cb_node = GetCBNode(dev_data, commandBuffer);
81319a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto render_pass_state = pRenderPassBegin ? GetRenderPassState(dev_data, pRenderPassBegin->renderPass) : nullptr;
81329a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto framebuffer = pRenderPassBegin ? GetFramebufferState(dev_data, pRenderPassBegin->framebuffer) : nullptr;
8133f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis    if (cb_node) {
8134308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski        if (render_pass_state) {
8135cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            uint32_t clear_op_size = 0;  // Make sure pClearValues is at least as large as last LOAD_OP_CLEAR
8136f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis            cb_node->activeFramebuffer = pRenderPassBegin->framebuffer;
8137308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski            for (uint32_t i = 0; i < render_pass_state->createInfo.attachmentCount; ++i) {
8138f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes                MT_FB_ATTACHMENT_INFO &fb_info = framebuffer->attachments[i];
8139308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski                auto pAttachment = &render_pass_state->createInfo.pAttachments[i];
8140bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                if (FormatSpecificLoadAndStoreOpSettings(pAttachment->format, pAttachment->loadOp, pAttachment->stencilLoadOp,
81411a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski                                                         VK_ATTACHMENT_LOAD_OP_CLEAR)) {
814292bc0680357019834b7529148ab6d73353ce02c7Mark Lobodzinski                    clear_op_size = static_cast<uint32_t>(i) + 1;
814316387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes                    std::function<bool()> function = [=]() {
81449a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                        SetImageMemoryValid(dev_data, GetImageState(dev_data, fb_info.image), true);
814516387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes                        return false;
814616387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes                    };
8147d807198f24437c1b2478ff1d06a33ce4873a1451Tobin Ehlis                    cb_node->queue_submit_functions.push_back(function);
8148db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes                } else if (FormatSpecificLoadAndStoreOpSettings(pAttachment->format, pAttachment->loadOp,
8149bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                                pAttachment->stencilLoadOp, VK_ATTACHMENT_LOAD_OP_DONT_CARE)) {
815016387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes                    std::function<bool()> function = [=]() {
81519a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                        SetImageMemoryValid(dev_data, GetImageState(dev_data, fb_info.image), false);
815216387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes                        return false;
815316387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes                    };
8154d807198f24437c1b2478ff1d06a33ce4873a1451Tobin Ehlis                    cb_node->queue_submit_functions.push_back(function);
8155db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes                } else if (FormatSpecificLoadAndStoreOpSettings(pAttachment->format, pAttachment->loadOp,
8156bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                                pAttachment->stencilLoadOp, VK_ATTACHMENT_LOAD_OP_LOAD)) {
815716387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes                    std::function<bool()> function = [=]() {
81589a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                        return ValidateImageMemoryIsValid(dev_data, GetImageState(dev_data, fb_info.image),
8159f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis                                                          "vkCmdBeginRenderPass()");
816016387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes                    };
8161d807198f24437c1b2478ff1d06a33ce4873a1451Tobin Ehlis                    cb_node->queue_submit_functions.push_back(function);
816216387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes                }
8163308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski                if (render_pass_state->attachment_first_read[i]) {
816416387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes                    std::function<bool()> function = [=]() {
81659a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                        return ValidateImageMemoryIsValid(dev_data, GetImageState(dev_data, fb_info.image),
8166f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis                                                          "vkCmdBeginRenderPass()");
816716387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes                    };
8168d807198f24437c1b2478ff1d06a33ce4873a1451Tobin Ehlis                    cb_node->queue_submit_functions.push_back(function);
81695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
81705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
81716de3c6ffa0819ee37cd5cecee918b062145e2ff1Tobin Ehlis            if (clear_op_size > pRenderPassBegin->clearValueCount) {
81723251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(
8173369cf6deef1fca74f9eb1f8ef6e96deba715b133Slawomir Cygan                    dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT,
8174315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                    HandleToUint64(render_pass_state->renderPass), __LINE__, VALIDATION_ERROR_1200070c, "DS",
8175bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                    "In vkCmdBeginRenderPass() the VkRenderPassBeginInfo struct has a clearValueCount of %u but there must "
8176bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                    "be at least %u entries in pClearValues array to account for the highest index attachment in renderPass "
8177cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                    "0x%" PRIx64
8178cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                    " that uses VK_ATTACHMENT_LOAD_OP_CLEAR is %u. Note that the pClearValues array "
8179bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                    "is indexed by attachment number so even if some pClearValues entries between 0 and %u correspond to "
8180bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                    "attachments that aren't cleared they will be ignored. %s",
81819b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                    pRenderPassBegin->clearValueCount, clear_op_size, HandleToUint64(render_pass_state->renderPass), clear_op_size,
8182315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                    clear_op_size - 1, validation_error_map[VALIDATION_ERROR_1200070c]);
8183369cf6deef1fca74f9eb1f8ef6e96deba715b133Slawomir Cygan            }
81843251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= VerifyRenderAreaBounds(dev_data, pRenderPassBegin);
81853251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= VerifyFramebufferAndRenderPassLayouts(dev_data, cb_node, pRenderPassBegin,
81863251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                                          GetFramebufferState(dev_data, pRenderPassBegin->framebuffer));
81879d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis            if (framebuffer->rp_state->renderPass != render_pass_state->renderPass) {
81889d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis                skip |= validateRenderPassCompatibility(dev_data, "render pass", render_pass_state, "framebuffer",
8189ba9be0cec36d930fc0d5a0cbfbc00b0df49b08e4Tobin Ehlis                                                        framebuffer->rp_state.get(), "vkCmdBeginRenderPass()",
8190ba9be0cec36d930fc0d5a0cbfbc00b0df49b08e4Tobin Ehlis                                                        VALIDATION_ERROR_12000710);
81919d5a67a009fe27e9b5404ec035ab84ed34332e5eTobin Ehlis            }
8192315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis            skip |= insideRenderPass(dev_data, cb_node, "vkCmdBeginRenderPass()", VALIDATION_ERROR_17a00017);
81933251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= ValidateDependencies(dev_data, framebuffer, render_pass_state);
8194315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis            skip |= validatePrimaryCommandBuffer(dev_data, cb_node, "vkCmdBeginRenderPass()", VALIDATION_ERROR_17a00019);
8195315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis            skip |= ValidateCmdQueueFlags(dev_data, cb_node, "vkCmdBeginRenderPass()", VK_QUEUE_GRAPHICS_BIT,
8196315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                          VALIDATION_ERROR_17a02415);
81973251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= ValidateCmd(dev_data, cb_node, CMD_BEGINRENDERPASS, "vkCmdBeginRenderPass()");
8198308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski            cb_node->activeRenderPass = render_pass_state;
81995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            // This is a shallow copy as that is all that is needed for now
8200f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis            cb_node->activeRenderPassBeginInfo = *pRenderPassBegin;
8201f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis            cb_node->activeSubpass = 0;
8202f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis            cb_node->activeSubpassContents = contents;
8203f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis            cb_node->framebuffers.insert(pRenderPassBegin->framebuffer);
8204883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis            // Connect this framebuffer and its children to this cmdBuffer
8205883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis            AddFramebufferBinding(dev_data, cb_node, framebuffer);
8206e03f0c649de6e228761ae301b57494db4eabe4aeTobin Ehlis            // Connect this RP to cmdBuffer
8207e03f0c649de6e228761ae301b57494db4eabe4aeTobin Ehlis            addCommandBufferBinding(&render_pass_state->cb_bindings,
8208e03f0c649de6e228761ae301b57494db4eabe4aeTobin Ehlis                                    {HandleToUint64(render_pass_state->renderPass), kVulkanObjectTypeRenderPass}, cb_node);
82095f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis            // transition attachments to the correct layouts for beginning of renderPass and first subpass
82105f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis            TransitionBeginRenderPassLayouts(dev_data, cb_node, render_pass_state, framebuffer);
82115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
82125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
8213b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
82143251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (!skip) {
82154a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.CmdBeginRenderPass(commandBuffer, pRenderPassBegin, contents);
82165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
82175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
82185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
821989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents) {
82203251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
822156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
8222ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
82239a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer);
82245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
8225315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= validatePrimaryCommandBuffer(dev_data, pCB, "vkCmdNextSubpass()", VALIDATION_ERROR_1b600019);
8226315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdNextSubpass()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_1b602415);
82273251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateCmd(dev_data, pCB, CMD_NEXTSUBPASS, "vkCmdNextSubpass()");
8228315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= outsideRenderPass(dev_data, pCB, "vkCmdNextSubpass()", VALIDATION_ERROR_1b600017);
822980281691386b37385846f21b38e8c9d4b12cc74eChris Forbes
8230fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes        auto subpassCount = pCB->activeRenderPass->createInfo.subpassCount;
823180281691386b37385846f21b38e8c9d4b12cc74eChris Forbes        if (pCB->activeSubpass == subpassCount - 1) {
82323251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
8233315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(commandBuffer), __LINE__, VALIDATION_ERROR_1b60071a, "DS",
82343251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "vkCmdNextSubpass(): Attempted to advance beyond final subpass. %s",
8235315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            validation_error_map[VALIDATION_ERROR_1b60071a]);
823680281691386b37385846f21b38e8c9d4b12cc74eChris Forbes        }
82375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
8238b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
823996ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes
82403251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (skip) return;
824196ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes
82424a0754042cf090e131e9e769d8a3633c228625beChris Forbes    dev_data->dispatch_table.CmdNextSubpass(commandBuffer, contents);
824396ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes
824496ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes    if (pCB) {
8245bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        lock.lock();
8246bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        pCB->activeSubpass++;
8247bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        pCB->activeSubpassContents = contents;
82485f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis        TransitionSubpassLayouts(dev_data, pCB, pCB->activeRenderPass, pCB->activeSubpass,
82499a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                                 GetFramebufferState(dev_data, pCB->activeRenderPassBeginInfo.framebuffer));
825096ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes    }
82515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
82525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
825389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdEndRenderPass(VkCommandBuffer commandBuffer) {
82543251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
825556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
8256ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
82579a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto pCB = GetCBNode(dev_data, commandBuffer);
825855867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski    FRAMEBUFFER_STATE *framebuffer = NULL;
825958c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes    if (pCB) {
8260127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis        RENDER_PASS_STATE *rp_state = pCB->activeRenderPass;
82619a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        framebuffer = GetFramebufferState(dev_data, pCB->activeFramebuffer);
8262127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis        if (rp_state) {
8263127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis            if (pCB->activeSubpass != rp_state->createInfo.subpassCount - 1) {
82643251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
82659b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, HandleToUint64(commandBuffer), __LINE__,
8266315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                VALIDATION_ERROR_1b00071c, "DS", "vkCmdEndRenderPass(): Called before reaching final subpass. %s",
8267315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                validation_error_map[VALIDATION_ERROR_1b00071c]);
826802a3382f28fc7c6ec6018165be88aa6fc4f05c9eChris Forbes            }
826902a3382f28fc7c6ec6018165be88aa6fc4f05c9eChris Forbes
8270127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis            for (size_t i = 0; i < rp_state->createInfo.attachmentCount; ++i) {
8271e3ad4b1284408353cc56a04951c1df1f35a636ceChris Forbes                MT_FB_ATTACHMENT_INFO &fb_info = framebuffer->attachments[i];
8272127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis                auto pAttachment = &rp_state->createInfo.pAttachments[i];
8273bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                if (FormatSpecificLoadAndStoreOpSettings(pAttachment->format, pAttachment->storeOp, pAttachment->stencilStoreOp,
8274bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                         VK_ATTACHMENT_STORE_OP_STORE)) {
827558c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes                    std::function<bool()> function = [=]() {
82769a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                        SetImageMemoryValid(dev_data, GetImageState(dev_data, fb_info.image), true);
827758c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes                        return false;
827858c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes                    };
8279d807198f24437c1b2478ff1d06a33ce4873a1451Tobin Ehlis                    pCB->queue_submit_functions.push_back(function);
8280db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes                } else if (FormatSpecificLoadAndStoreOpSettings(pAttachment->format, pAttachment->storeOp,
8281bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                                pAttachment->stencilStoreOp, VK_ATTACHMENT_STORE_OP_DONT_CARE)) {
828258c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes                    std::function<bool()> function = [=]() {
82839a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                        SetImageMemoryValid(dev_data, GetImageState(dev_data, fb_info.image), false);
828458c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes                        return false;
828558c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes                    };
8286d807198f24437c1b2478ff1d06a33ce4873a1451Tobin Ehlis                    pCB->queue_submit_functions.push_back(function);
82875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
82885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
82895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
8290315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= outsideRenderPass(dev_data, pCB, "vkCmdEndRenderpass()", VALIDATION_ERROR_1b000017);
8291315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= validatePrimaryCommandBuffer(dev_data, pCB, "vkCmdEndRenderPass()", VALIDATION_ERROR_1b000019);
8292315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdEndRenderPass()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_1b002415);
82933251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateCmd(dev_data, pCB, CMD_ENDRENDERPASS, "vkCmdEndRenderPass()");
82940e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes    }
82950e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes    lock.unlock();
82960e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes
82973251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (skip) return;
82980e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes
82994a0754042cf090e131e9e769d8a3633c228625beChris Forbes    dev_data->dispatch_table.CmdEndRenderPass(commandBuffer);
83000e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes
83010e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes    if (pCB) {
83020e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes        lock.lock();
830355867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski        TransitionFinalSubpassLayouts(dev_data, pCB, &pCB->activeRenderPassBeginInfo, framebuffer);
830458c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes        pCB->activeRenderPass = nullptr;
830558c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes        pCB->activeSubpass = 0;
830658c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes        pCB->activeFramebuffer = VK_NULL_HANDLE;
83075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
83085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
83095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
8310e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool validateFramebuffer(layer_data *dev_data, VkCommandBuffer primaryBuffer, const GLOBAL_CB_NODE *pCB,
831194983abdca3266bfd87e708f31fda2b56b1b547dTobin Ehlis                                VkCommandBuffer secondaryBuffer, const GLOBAL_CB_NODE *pSubCB, const char *caller) {
83123251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
83135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (!pSubCB->beginInfo.pInheritanceInfo) {
83143251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        return skip;
83155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
8316c5b97dda856ff837638b3ebb7e231d5507c495a3Chris Forbes    VkFramebuffer primary_fb = pCB->activeFramebuffer;
83175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    VkFramebuffer secondary_fb = pSubCB->beginInfo.pInheritanceInfo->framebuffer;
83185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (secondary_fb != VK_NULL_HANDLE) {
83195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (primary_fb != secondary_fb) {
83203251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
8321315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(primaryBuffer), __LINE__, VALIDATION_ERROR_1b2000c6, "DS",
83223251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "vkCmdExecuteCommands() called w/ invalid secondary command buffer 0x%" PRIx64
83233251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            " which has a framebuffer 0x%" PRIx64
83243251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            " that is not the same as the primary command buffer's current active framebuffer 0x%" PRIx64 ". %s",
83259b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(secondaryBuffer), HandleToUint64(secondary_fb), HandleToUint64(primary_fb),
8326315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            validation_error_map[VALIDATION_ERROR_1b2000c6]);
83275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
83289a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto fb = GetFramebufferState(dev_data, secondary_fb);
8329e3ad4b1284408353cc56a04951c1df1f35a636ceChris Forbes        if (!fb) {
83303251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
83319b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(primaryBuffer), __LINE__, DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS",
83323251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "vkCmdExecuteCommands() called w/ invalid Cmd Buffer 0x%p "
83333251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "which has invalid framebuffer 0x%" PRIx64 ".",
83349b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            (void *)secondaryBuffer, HandleToUint64(secondary_fb));
83353251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            return skip;
83365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
83375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
83383251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
83395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
83405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
8341e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool validateSecondaryCommandBufferState(layer_data *dev_data, GLOBAL_CB_NODE *pCB, GLOBAL_CB_NODE *pSubCB) {
83423251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
83435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    unordered_set<int> activeTypes;
83445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (auto queryObject : pCB->activeQueries) {
83455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        auto queryPoolData = dev_data->queryPoolMap.find(queryObject.pool);
83465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (queryPoolData != dev_data->queryPoolMap.end()) {
83475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (queryPoolData->second.createInfo.queryType == VK_QUERY_TYPE_PIPELINE_STATISTICS &&
83485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                pSubCB->beginInfo.pInheritanceInfo) {
83495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                VkQueryPipelineStatisticFlags cmdBufStatistics = pSubCB->beginInfo.pInheritanceInfo->pipelineStatistics;
83505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                if ((cmdBufStatistics & queryPoolData->second.createInfo.pipelineStatistics) != cmdBufStatistics) {
83519b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                    skip |= log_msg(
83529b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
8353315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(pCB->commandBuffer), __LINE__, VALIDATION_ERROR_1b2000d0, "DS",
83549b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        "vkCmdExecuteCommands() called w/ invalid Cmd Buffer 0x%p "
83559b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        "which has invalid active query pool 0x%" PRIx64
83569b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        ". Pipeline statistics is being queried so the command "
83579b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        "buffer must have all bits set on the queryPool. %s",
8358315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        pCB->commandBuffer, HandleToUint64(queryPoolData->first), validation_error_map[VALIDATION_ERROR_1b2000d0]);
83595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
83605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
83615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            activeTypes.insert(queryPoolData->second.createInfo.queryType);
83625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
83635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
83645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (auto queryObject : pSubCB->startedQueries) {
83655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        auto queryPoolData = dev_data->queryPoolMap.find(queryObject.pool);
83665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        if (queryPoolData != dev_data->queryPoolMap.end() && activeTypes.count(queryPoolData->second.createInfo.queryType)) {
83679b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
83689b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS",
83699b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            "vkCmdExecuteCommands() called w/ invalid Cmd Buffer 0x%p "
83709b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            "which has invalid active query pool 0x%" PRIx64
83719b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            "of type %d but a query of that type has been started on "
83729b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            "secondary Cmd Buffer 0x%p.",
83739b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            pCB->commandBuffer, HandleToUint64(queryPoolData->first), queryPoolData->second.createInfo.queryType,
83749b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            pSubCB->commandBuffer);
83755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
83765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
83777bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski
83789a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto primary_pool = GetCommandPoolNode(dev_data, pCB->createInfo.commandPool);
83799a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto secondary_pool = GetCommandPoolNode(dev_data, pSubCB->createInfo.commandPool);
83807bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski    if (primary_pool && secondary_pool && (primary_pool->queueFamilyIndex != secondary_pool->queueFamilyIndex)) {
83813251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |=
8382226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis            log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
83839b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                    HandleToUint64(pSubCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_QUEUE_FAMILY, "DS",
8384226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis                    "vkCmdExecuteCommands(): Primary command buffer 0x%p"
8385226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis                    " created in queue family %d has secondary command buffer 0x%p created in queue family %d.",
8386226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis                    pCB->commandBuffer, primary_pool->queueFamilyIndex, pSubCB->commandBuffer, secondary_pool->queueFamilyIndex);
83877bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski    }
83887bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski
83893251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    return skip;
83905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
83915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
8392bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t commandBuffersCount,
8393bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                              const VkCommandBuffer *pCommandBuffers) {
83943251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
839556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
8396ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
83979a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer);
83985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (pCB) {
83995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        GLOBAL_CB_NODE *pSubCB = NULL;
84005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        for (uint32_t i = 0; i < commandBuffersCount; i++) {
84019a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            pSubCB = GetCBNode(dev_data, pCommandBuffers[i]);
84020a8b955c23012196339f3c10ffedc631ea0f7c58Tobin Ehlis            assert(pSubCB);
84030a8b955c23012196339f3c10ffedc631ea0f7c58Tobin Ehlis            if (VK_COMMAND_BUFFER_LEVEL_PRIMARY == pSubCB->createInfo.level) {
84043251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |=
8405df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
8406315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(pCommandBuffers[i]), __LINE__, VALIDATION_ERROR_1b2000b0, "DS",
8407df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                            "vkCmdExecuteCommands() called w/ Primary Cmd Buffer 0x%p in element %u of pCommandBuffers "
8408df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski                            "array. All cmd buffers in pCommandBuffers array must be secondary. %s",
8409315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            pCommandBuffers[i], i, validation_error_map[VALIDATION_ERROR_1b2000b0]);
8410cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            } else if (pCB->activeRenderPass) {  // Secondary CB w/i RenderPass must have *CONTINUE_BIT set
84110de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                if (pSubCB->beginInfo.pInheritanceInfo != nullptr) {
84120de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                    auto secondary_rp_state = GetRenderPassState(dev_data, pSubCB->beginInfo.pInheritanceInfo->renderPass);
84130de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                    if (!(pSubCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT)) {
84140de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                        skip |= log_msg(
84150de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                            dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
8416315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(pCommandBuffers[i]), __LINE__, VALIDATION_ERROR_1b2000c0, "DS",
84170de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                            "vkCmdExecuteCommands(): Secondary Command Buffer (0x%p) executed within render pass (0x%" PRIxLEAST64
84180de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                            ") must have had vkBeginCommandBuffer() called w/ VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT "
84190de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                            "set. %s",
84200de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                            pCommandBuffers[i], HandleToUint64(pCB->activeRenderPass->renderPass),
8421315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            validation_error_map[VALIDATION_ERROR_1b2000c0]);
84220de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                    } else {
84230de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                        // Make sure render pass is compatible with parent command buffer pass if has continue
84240de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                        if (pCB->activeRenderPass->renderPass != secondary_rp_state->renderPass) {
842594983abdca3266bfd87e708f31fda2b56b1b547dTobin Ehlis                            skip |= validateRenderPassCompatibility(dev_data, "primary command buffer", pCB->activeRenderPass,
842694983abdca3266bfd87e708f31fda2b56b1b547dTobin Ehlis                                                                    "secondary command buffer", secondary_rp_state,
842794983abdca3266bfd87e708f31fda2b56b1b547dTobin Ehlis                                                                    "vkCmdExecuteCommands()", VALIDATION_ERROR_1b2000c4);
84280de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                        }
84290de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                        //  If framebuffer for secondary CB is not NULL, then it must match active FB from primaryCB
843094983abdca3266bfd87e708f31fda2b56b1b547dTobin Ehlis                        skip |=
843194983abdca3266bfd87e708f31fda2b56b1b547dTobin Ehlis                            validateFramebuffer(dev_data, commandBuffer, pCB, pCommandBuffers[i], pSubCB, "vkCmdExecuteCommands()");
8432f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                        if (VK_NULL_HANDLE == pSubCB->activeFramebuffer) {
843379fc00370d55e7cbfd4052b579120e64b0a1a4beTobin Ehlis                            //  Inherit primary's activeFramebuffer and while running validate functions
843479fc00370d55e7cbfd4052b579120e64b0a1a4beTobin Ehlis                            for (auto &function : pSubCB->cmd_execute_commands_functions) {
843579fc00370d55e7cbfd4052b579120e64b0a1a4beTobin Ehlis                                skip |= function(pCB->activeFramebuffer);
8436f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                            }
8437f384f33742c2b72888372332747298d08135ac92Tobin Ehlis                        }
84380de5f3bbf5218c9bc92c5bb09c8547bd26adcabcMark Lobodzinski                    }
84395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
84405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
84415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            // TODO(mlentine): Move more logic into this method
84423251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= validateSecondaryCommandBufferState(dev_data, pCB, pSubCB);
8443315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis            skip |= validateCommandBufferState(dev_data, pSubCB, "vkCmdExecuteCommands()", 0, VALIDATION_ERROR_1b2000b2);
84445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            if (!(pSubCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT)) {
84459b2582dc67737351a72fbeb82e9e6e8cdff7a026Chris Forbes                if (pSubCB->in_use.load() || pCB->linkedCommandBuffers.count(pSubCB)) {
84463251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
84479b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                    VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, HandleToUint64(pCB->commandBuffer), __LINE__,
8448315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    VALIDATION_ERROR_1b2000b4, "DS",
84493251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    "Attempt to simultaneously execute command buffer 0x%p"
84503251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    " without VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT set! %s",
8451315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                    pCB->commandBuffer, validation_error_map[VALIDATION_ERROR_1b2000b4]);
84525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
84535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                if (pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT) {
84545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    // Warn that non-simultaneous secondary cmd buffer renders primary non-simultaneous
84553251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= log_msg(
84565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
84579b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        HandleToUint64(pCommandBuffers[i]), __LINE__, DRAWSTATE_INVALID_CB_SIMULTANEOUS_USE, "DS",
8458226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis                        "vkCmdExecuteCommands(): Secondary Command Buffer (0x%p) "
8459226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis                        "does not have VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT set and will cause primary command buffer "
8460226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis                        "(0x%p) to be treated as if it does not have VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT "
846183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis                        "set, even though it does.",
8462226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis                        pCommandBuffers[i], pCB->commandBuffer);
84635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    pCB->beginInfo.flags &= ~VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
84645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
84655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
8466f71dd305f197826a61f398bff725267a20ea1d90Chris Forbes            if (!pCB->activeQueries.empty() && !dev_data->enabled_features.inheritedQueries) {
84673251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |=
8468cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
8469315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(pCommandBuffers[i]), __LINE__, VALIDATION_ERROR_1b2000ca, "DS",
8470cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                            "vkCmdExecuteCommands(): Secondary Command Buffer "
8471cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                            "(0x%p) cannot be submitted with a query in "
8472cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                            "flight and inherited queries not "
8473cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                            "supported on this device. %s",
8474315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            pCommandBuffers[i], validation_error_map[VALIDATION_ERROR_1b2000ca]);
84755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
84769b2582dc67737351a72fbeb82e9e6e8cdff7a026Chris Forbes            // TODO: separate validate from update! This is very tangled.
84778567fecbf563420f5900ade277ca68908aa87259Tobin Ehlis            // Propagate layout transitions to the primary cmd buffer
84788567fecbf563420f5900ade277ca68908aa87259Tobin Ehlis            for (auto ilm_entry : pSubCB->imageLayoutMap) {
84791fdcd3bc7fbd85f567a8270f6b7354c6f7b67661Alex Smith                if (pCB->imageLayoutMap.find(ilm_entry.first) != pCB->imageLayoutMap.end()) {
84801fdcd3bc7fbd85f567a8270f6b7354c6f7b67661Alex Smith                    pCB->imageLayoutMap[ilm_entry.first].layout = ilm_entry.second.layout;
84811fdcd3bc7fbd85f567a8270f6b7354c6f7b67661Alex Smith                } else {
84821fdcd3bc7fbd85f567a8270f6b7354c6f7b67661Alex Smith                    assert(ilm_entry.first.hasSubresource);
84831fdcd3bc7fbd85f567a8270f6b7354c6f7b67661Alex Smith                    IMAGE_CMD_BUF_LAYOUT_NODE node;
84841fdcd3bc7fbd85f567a8270f6b7354c6f7b67661Alex Smith                    if (!FindCmdBufLayout(dev_data, pCB, ilm_entry.first.image, ilm_entry.first.subresource, node)) {
84851fdcd3bc7fbd85f567a8270f6b7354c6f7b67661Alex Smith                        node.initialLayout = ilm_entry.second.initialLayout;
84861fdcd3bc7fbd85f567a8270f6b7354c6f7b67661Alex Smith                    }
84871fdcd3bc7fbd85f567a8270f6b7354c6f7b67661Alex Smith                    node.layout = ilm_entry.second.layout;
84881fdcd3bc7fbd85f567a8270f6b7354c6f7b67661Alex Smith                    SetLayout(dev_data, pCB, ilm_entry.first, node);
84891fdcd3bc7fbd85f567a8270f6b7354c6f7b67661Alex Smith                }
84908567fecbf563420f5900ade277ca68908aa87259Tobin Ehlis            }
84915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            pSubCB->primaryCommandBuffer = pCB->commandBuffer;
84921a3660584634742a3297915c94768d73f360e794Chris Forbes            pCB->linkedCommandBuffers.insert(pSubCB);
84931a3660584634742a3297915c94768d73f360e794Chris Forbes            pSubCB->linkedCommandBuffers.insert(pCB);
8494d4ee9fdb2def1e9dc70c5627c9103e264471b8ebMichael Lentine            for (auto &function : pSubCB->queryUpdates) {
8495d4ee9fdb2def1e9dc70c5627c9103e264471b8ebMichael Lentine                pCB->queryUpdates.push_back(function);
8496d4ee9fdb2def1e9dc70c5627c9103e264471b8ebMichael Lentine            }
849775c6d3c8ccf58c2b4bb5eb14e8e6763b254bdc17Alex Smith            for (auto &function : pSubCB->queue_submit_functions) {
849875c6d3c8ccf58c2b4bb5eb14e8e6763b254bdc17Alex Smith                pCB->queue_submit_functions.push_back(function);
849975c6d3c8ccf58c2b4bb5eb14e8e6763b254bdc17Alex Smith            }
85005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
8501315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |= validatePrimaryCommandBuffer(dev_data, pCB, "vkCmdExecuteCommands()", VALIDATION_ERROR_1b200019);
8502315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis        skip |=
8503315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis            ValidateCmdQueueFlags(dev_data, pCB, "vkCmdExecuteCommands()",
8504315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                  VK_QUEUE_TRANSFER_BIT | VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, VALIDATION_ERROR_1b202415);
8505f5a52627a6576d3d532cd1f2e1be6d9987aeda7fChris Forbes        skip |= ValidateCmd(dev_data, pCB, CMD_EXECUTECOMMANDS, "vkCmdExecuteCommands()");
85065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
8507b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
85083251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (!skip) dev_data->dispatch_table.CmdExecuteCommands(commandBuffer, commandBuffersCount, pCommandBuffers);
85095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
85105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
8511bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL MapMemory(VkDevice device, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size, VkFlags flags,
8512bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                         void **ppData) {
851356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
85145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
85153251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
85165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
8517ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
85189a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    DEVICE_MEM_INFO *mem_info = GetMemObjInfo(dev_data, mem);
8519cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis    if (mem_info) {
8520f541bf53dee6daf82a4c8304354eac599a884d29Tobin Ehlis        // TODO : This could me more fine-grained to track just region that is valid
8521f541bf53dee6daf82a4c8304354eac599a884d29Tobin Ehlis        mem_info->global_valid = true;
8522623548a271287ae55415e45e3c654ee66d4e79ffTobin Ehlis        auto end_offset = (VK_WHOLE_SIZE == size) ? mem_info->alloc_info.allocationSize - 1 : offset + size - 1;
85233251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateMapImageLayouts(dev_data, device, mem_info, offset, end_offset);
8524cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis        // TODO : Do we need to create new "bound_range" for the mapped range?
8525623548a271287ae55415e45e3c654ee66d4e79ffTobin Ehlis        SetMemRangesValid(dev_data, mem_info, offset, end_offset);
8526cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis        if ((dev_data->phys_dev_mem_props.memoryTypes[mem_info->alloc_info.memoryTypeIndex].propertyFlags &
8527b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis             VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0) {
85283251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
8529315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                           HandleToUint64(mem), __LINE__, VALIDATION_ERROR_31200554, "MEM",
85303251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                           "Mapping Memory without VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT set: mem obj 0x%" PRIxLEAST64 ". %s",
8531315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                           HandleToUint64(mem), validation_error_map[VALIDATION_ERROR_31200554]);
85325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
85335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
85343251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    skip |= ValidateMapMemRange(dev_data, mem, offset, size);
8535b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
85365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
85373251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (!skip) {
85384a0754042cf090e131e9e769d8a3633c228625beChris Forbes        result = dev_data->dispatch_table.MapMemory(device, mem, offset, size, flags, ppData);
85397c0012acb5327961b0a5191434a08e5fa788786dTobin Ehlis        if (VK_SUCCESS == result) {
85407c0012acb5327961b0a5191434a08e5fa788786dTobin Ehlis            lock.lock();
8541cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis            // TODO : What's the point of this range? See comment on creating new "bound_range" above, which may replace this
85427c0012acb5327961b0a5191434a08e5fa788786dTobin Ehlis            storeMemRanges(dev_data, mem, offset, size);
85435f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            initializeAndTrackMemory(dev_data, mem, offset, size, ppData);
85447c0012acb5327961b0a5191434a08e5fa788786dTobin Ehlis            lock.unlock();
85457c0012acb5327961b0a5191434a08e5fa788786dTobin Ehlis        }
85465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
85475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
85485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
85495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
855089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL UnmapMemory(VkDevice device, VkDeviceMemory mem) {
855156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
85523251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
85535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
8554ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
85553251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    skip |= deleteMemRanges(dev_data, mem);
8556b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
85573251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (!skip) {
85584a0754042cf090e131e9e769d8a3633c228625beChris Forbes        dev_data->dispatch_table.UnmapMemory(device, mem);
85595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
85605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
85615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
85628860b85a52096f9f9b28616bc37feed505497a54Chris Forbesstatic bool validateMemoryIsMapped(layer_data *dev_data, const char *funcName, uint32_t memRangeCount,
8563e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves                                   const VkMappedMemoryRange *pMemRanges) {
8564c7ee6f2fe100c1aacfaa0872832717c906bb8a4aMark Lobodzinski    bool skip = false;
85655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    for (uint32_t i = 0; i < memRangeCount; ++i) {
85669a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto mem_info = GetMemObjInfo(dev_data, pMemRanges[i].memory);
856757fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis        if (mem_info) {
8568f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski            if (pMemRanges[i].size == VK_WHOLE_SIZE) {
8569f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski                if (mem_info->mem_range.offset > pMemRanges[i].offset) {
8570315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                    skip |=
8571315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
8572315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                HandleToUint64(pMemRanges[i].memory), __LINE__, VALIDATION_ERROR_0c20055c, "MEM",
8573315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                "%s: Flush/Invalidate offset (" PRINTF_SIZE_T_SPECIFIER
8574315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                ") is less than Memory Object's offset "
8575315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                "(" PRINTF_SIZE_T_SPECIFIER "). %s",
8576315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                funcName, static_cast<size_t>(pMemRanges[i].offset),
8577315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                static_cast<size_t>(mem_info->mem_range.offset), validation_error_map[VALIDATION_ERROR_0c20055c]);
8578f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski                }
8579f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski            } else {
8580f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski                const uint64_t data_end = (mem_info->mem_range.size == VK_WHOLE_SIZE)
8581f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski                                              ? mem_info->alloc_info.allocationSize
8582f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski                                              : (mem_info->mem_range.offset + mem_info->mem_range.size);
8583f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski                if ((mem_info->mem_range.offset > pMemRanges[i].offset) ||
8584f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski                    (data_end < (pMemRanges[i].offset + pMemRanges[i].size))) {
8585c7ee6f2fe100c1aacfaa0872832717c906bb8a4aMark Lobodzinski                    skip |=
8586f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski                        log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
8587315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                HandleToUint64(pMemRanges[i].memory), __LINE__, VALIDATION_ERROR_0c20055a, "MEM",
8588f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski                                "%s: Flush/Invalidate size or offset (" PRINTF_SIZE_T_SPECIFIER ", " PRINTF_SIZE_T_SPECIFIER
8589f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski                                ") exceed the Memory Object's upper-bound "
8590f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski                                "(" PRINTF_SIZE_T_SPECIFIER "). %s",
8591f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski                                funcName, static_cast<size_t>(pMemRanges[i].offset + pMemRanges[i].size),
8592f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski                                static_cast<size_t>(pMemRanges[i].offset), static_cast<size_t>(data_end),
8593315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                validation_error_map[VALIDATION_ERROR_0c20055a]);
8594f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski                }
85955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
85965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
85975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
8598c7ee6f2fe100c1aacfaa0872832717c906bb8a4aMark Lobodzinski    return skip;
85995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
86005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
8601bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinskistatic bool ValidateAndCopyNoncoherentMemoryToDriver(layer_data *dev_data, uint32_t mem_range_count,
8602bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski                                                     const VkMappedMemoryRange *mem_ranges) {
8603bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski    bool skip = false;
8604bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski    for (uint32_t i = 0; i < mem_range_count; ++i) {
86059a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto mem_info = GetMemObjInfo(dev_data, mem_ranges[i].memory);
860657fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis        if (mem_info) {
86075f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            if (mem_info->shadow_copy) {
86085f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski                VkDeviceSize size = (mem_info->mem_range.size != VK_WHOLE_SIZE)
86095f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski                                        ? mem_info->mem_range.size
8610d8a53ade6b5501256798a8b4ec0bc14f72adc1faTobin Ehlis                                        : (mem_info->alloc_info.allocationSize - mem_info->mem_range.offset);
86115f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski                char *data = static_cast<char *>(mem_info->shadow_copy);
86125f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski                for (uint64_t j = 0; j < mem_info->shadow_pad_size; ++j) {
86135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    if (data[j] != NoncoherentMemoryFillValue) {
86149b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        skip |= log_msg(
86159b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
86169b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(mem_ranges[i].memory), __LINE__, MEMTRACK_INVALID_MAP, "MEM",
86179b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            "Memory underflow was detected on mem obj 0x%" PRIxLEAST64, HandleToUint64(mem_ranges[i].memory));
86185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    }
86195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
86205f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski                for (uint64_t j = (size + mem_info->shadow_pad_size); j < (2 * mem_info->shadow_pad_size + size); ++j) {
86215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    if (data[j] != NoncoherentMemoryFillValue) {
86229b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        skip |= log_msg(
86239b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
86249b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(mem_ranges[i].memory), __LINE__, MEMTRACK_INVALID_MAP, "MEM",
86259b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            "Memory overflow was detected on mem obj 0x%" PRIxLEAST64, HandleToUint64(mem_ranges[i].memory));
86265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    }
86275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
86285f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski                memcpy(mem_info->p_driver_data, static_cast<void *>(data + mem_info->shadow_pad_size), (size_t)(size));
86295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
86305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
86315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
8632bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski    return skip;
86335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
86345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
8635bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinskistatic void CopyNoncoherentMemoryFromDriver(layer_data *dev_data, uint32_t mem_range_count, const VkMappedMemoryRange *mem_ranges) {
8636bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski    for (uint32_t i = 0; i < mem_range_count; ++i) {
86379a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto mem_info = GetMemObjInfo(dev_data, mem_ranges[i].memory);
86385f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski        if (mem_info && mem_info->shadow_copy) {
86395f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            VkDeviceSize size = (mem_info->mem_range.size != VK_WHOLE_SIZE)
86405f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski                                    ? mem_info->mem_range.size
86415f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski                                    : (mem_info->alloc_info.allocationSize - mem_ranges[i].offset);
86425f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            char *data = static_cast<char *>(mem_info->shadow_copy);
86435f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski            memcpy(data + mem_info->shadow_pad_size, mem_info->p_driver_data, (size_t)(size));
86449e21e56fc23ade48efd3752d2e2729895eb90349Mark Lobodzinski        }
86459e21e56fc23ade48efd3752d2e2729895eb90349Mark Lobodzinski    }
86469e21e56fc23ade48efd3752d2e2729895eb90349Mark Lobodzinski}
86479e21e56fc23ade48efd3752d2e2729895eb90349Mark Lobodzinski
8648ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinskistatic bool ValidateMappedMemoryRangeDeviceLimits(layer_data *dev_data, const char *func_name, uint32_t mem_range_count,
8649ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski                                                  const VkMappedMemoryRange *mem_ranges) {
8650ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski    bool skip = false;
8651ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski    for (uint32_t i = 0; i < mem_range_count; ++i) {
8652ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski        uint64_t atom_size = dev_data->phys_dev_properties.properties.limits.nonCoherentAtomSize;
865316769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton        if (SafeModulo(mem_ranges[i].offset, atom_size) != 0) {
8654df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
8655315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(mem_ranges->memory), __LINE__, VALIDATION_ERROR_0c20055e, "MEM",
8656ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski                            "%s: Offset in pMemRanges[%d] is 0x%" PRIxLEAST64
8657ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski                            ", which is not a multiple of VkPhysicalDeviceLimits::nonCoherentAtomSize (0x%" PRIxLEAST64 "). %s",
8658315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            func_name, i, mem_ranges[i].offset, atom_size, validation_error_map[VALIDATION_ERROR_0c20055e]);
8659ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski        }
866016769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton        if ((mem_ranges[i].size != VK_WHOLE_SIZE) && (SafeModulo(mem_ranges[i].size, atom_size) != 0)) {
8661df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
8662315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(mem_ranges->memory), __LINE__, VALIDATION_ERROR_0c200560, "MEM",
8663ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski                            "%s: Size in pMemRanges[%d] is 0x%" PRIxLEAST64
8664ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski                            ", which is not a multiple of VkPhysicalDeviceLimits::nonCoherentAtomSize (0x%" PRIxLEAST64 "). %s",
8665315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            func_name, i, mem_ranges[i].size, atom_size, validation_error_map[VALIDATION_ERROR_0c200560]);
8666ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski        }
8667ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski    }
8668ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski    return skip;
8669ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski}
8670ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski
867180e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinskistatic bool PreCallValidateFlushMappedMemoryRanges(layer_data *dev_data, uint32_t mem_range_count,
867280e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski                                                   const VkMappedMemoryRange *mem_ranges) {
867380e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski    bool skip = false;
8674ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    lock_guard_t lock(global_lock);
867580e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski    skip |= ValidateAndCopyNoncoherentMemoryToDriver(dev_data, mem_range_count, mem_ranges);
867680e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski    skip |= validateMemoryIsMapped(dev_data, "vkFlushMappedMemoryRanges", mem_range_count, mem_ranges);
867780e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski    return skip;
867880e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski}
867980e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski
8680bba0de708d942e9a2187158915856995db1c5a4dMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL FlushMappedMemoryRanges(VkDevice device, uint32_t memRangeCount,
8681bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski                                                       const VkMappedMemoryRange *pMemRanges) {
86825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
868356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
86845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
868580e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski    if (!PreCallValidateFlushMappedMemoryRanges(dev_data, memRangeCount, pMemRanges)) {
86864a0754042cf090e131e9e769d8a3633c228625beChris Forbes        result = dev_data->dispatch_table.FlushMappedMemoryRanges(device, memRangeCount, pMemRanges);
86875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
86885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
86895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
86905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
869180e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinskistatic bool PreCallValidateInvalidateMappedMemoryRanges(layer_data *dev_data, uint32_t mem_range_count,
869280e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski                                                        const VkMappedMemoryRange *mem_ranges) {
869380e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski    bool skip = false;
8694ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    lock_guard_t lock(global_lock);
869580e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski    skip |= validateMemoryIsMapped(dev_data, "vkInvalidateMappedMemoryRanges", mem_range_count, mem_ranges);
869680e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski    return skip;
869780e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski}
869880e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski
869980e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinskistatic void PostCallRecordInvalidateMappedMemoryRanges(layer_data *dev_data, uint32_t mem_range_count,
870080e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski                                                       const VkMappedMemoryRange *mem_ranges) {
8701ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    lock_guard_t lock(global_lock);
870280e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski    // Update our shadow copy with modified driver data
870380e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski    CopyNoncoherentMemoryFromDriver(dev_data, mem_range_count, mem_ranges);
870480e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski}
870580e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski
8706bba0de708d942e9a2187158915856995db1c5a4dMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL InvalidateMappedMemoryRanges(VkDevice device, uint32_t memRangeCount,
8707bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski                                                            const VkMappedMemoryRange *pMemRanges) {
87085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
870956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
87105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
871180e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski    if (!PreCallValidateInvalidateMappedMemoryRanges(dev_data, memRangeCount, pMemRanges)) {
87124a0754042cf090e131e9e769d8a3633c228625beChris Forbes        result = dev_data->dispatch_table.InvalidateMappedMemoryRanges(device, memRangeCount, pMemRanges);
871380e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski        if (result == VK_SUCCESS) {
871480e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski            PostCallRecordInvalidateMappedMemoryRanges(dev_data, memRangeCount, pMemRanges);
871580e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski        }
87165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
87175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
87185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
87195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
8720160335c453ec51cc48bdef78e8befdb3c86ff292Cort Strattonstatic bool PreCallValidateBindImageMemory(layer_data *dev_data, VkImage image, IMAGE_STATE *image_state, VkDeviceMemory mem,
8721160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton                                           VkDeviceSize memoryOffset) {
87220109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski    bool skip = false;
87231facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis    if (image_state) {
8724ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes        unique_lock_t lock(global_lock);
872594c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis        // Track objects tied to memory
87269b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus        uint64_t image_handle = HandleToUint64(image);
87277a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski        skip = ValidateSetMemBinding(dev_data, mem, image_handle, kVulkanObjectTypeImage, "vkBindImageMemory()");
8728ff3ef1181960319d2268e82dae075726f650c553Tobin Ehlis        if (!image_state->memory_requirements_checked) {
8729ff3ef1181960319d2268e82dae075726f650c553Tobin Ehlis            // There's not an explicit requirement in the spec to call vkGetImageMemoryRequirements() prior to calling
8730341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton            // BindImageMemory but it's implied in that memory being bound must conform with VkMemoryRequirements from
8731341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton            // vkGetImageMemoryRequirements()
87320109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
87330109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski                            image_handle, __LINE__, DRAWSTATE_INVALID_IMAGE, "DS",
87340109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski                            "vkBindImageMemory(): Binding memory to image 0x%" PRIxLEAST64
87350109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski                            " but vkGetImageMemoryRequirements() has not been called on that image.",
87360109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski                            image_handle);
8737ff3ef1181960319d2268e82dae075726f650c553Tobin Ehlis            // Make the call for them so we can verify the state
8738ff3ef1181960319d2268e82dae075726f650c553Tobin Ehlis            lock.unlock();
8739341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton            dev_data->dispatch_table.GetImageMemoryRequirements(dev_data->device, image, &image_state->requirements);
8740ff3ef1181960319d2268e82dae075726f650c553Tobin Ehlis            lock.lock();
8741ff3ef1181960319d2268e82dae075726f650c553Tobin Ehlis        }
874247aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski
87430ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton        // Validate bound memory range information
87449a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto mem_info = GetMemObjInfo(dev_data, mem);
874557fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis        if (mem_info) {
87460ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton            skip |= ValidateInsertImageMemoryRange(dev_data, image, mem_info, memoryOffset, image_state->requirements,
87470ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton                                                   image_state->createInfo.tiling == VK_IMAGE_TILING_LINEAR, "vkBindImageMemory()");
874874300755ed9ec780d6073af71e47f201217008d6Cort Stratton            skip |= ValidateMemoryTypes(dev_data, mem_info, image_state->requirements.memoryTypeBits, "vkBindImageMemory()",
8749315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                        VALIDATION_ERROR_1740082e);
875047aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski        }
8751160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton
8752160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton        // Validate memory requirements alignment
875316769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton        if (SafeModulo(memoryOffset, image_state->requirements.alignment) != 0) {
8754160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
8755315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            image_handle, __LINE__, VALIDATION_ERROR_17400830, "DS",
8756160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton                            "vkBindImageMemory(): memoryOffset is 0x%" PRIxLEAST64
8757160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton                            " but must be an integer multiple of the "
8758160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton                            "VkMemoryRequirements::alignment value 0x%" PRIxLEAST64
8759160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton                            ", returned from a call to vkGetImageMemoryRequirements with image. %s",
8760315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            memoryOffset, image_state->requirements.alignment, validation_error_map[VALIDATION_ERROR_17400830]);
8761160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton        }
8762160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton
8763160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton        // Validate memory requirements size
8764160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton        if (image_state->requirements.size > mem_info->alloc_info.allocationSize - memoryOffset) {
8765160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
8766315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            image_handle, __LINE__, VALIDATION_ERROR_17400832, "DS",
8767160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton                            "vkBindImageMemory(): memory size minus memoryOffset is 0x%" PRIxLEAST64
8768160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton                            " but must be at least as large as "
8769160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton                            "VkMemoryRequirements::size value 0x%" PRIxLEAST64
8770160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton                            ", returned from a call to vkGetImageMemoryRequirements with image. %s",
8771160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton                            mem_info->alloc_info.allocationSize - memoryOffset, image_state->requirements.size,
8772315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            validation_error_map[VALIDATION_ERROR_17400832]);
8773160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton        }
8774341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton    }
8775341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton    return skip;
8776341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton}
877747aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski
8778160335c453ec51cc48bdef78e8befdb3c86ff292Cort Strattonstatic void PostCallRecordBindImageMemory(layer_data *dev_data, VkImage image, IMAGE_STATE *image_state, VkDeviceMemory mem,
8779160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton                                          VkDeviceSize memoryOffset) {
8780341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton    if (image_state) {
8781ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes        unique_lock_t lock(global_lock);
87820ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton        // Track bound memory range information
87830ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton        auto mem_info = GetMemObjInfo(dev_data, mem);
87840ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton        if (mem_info) {
87850ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton            InsertImageMemoryRange(dev_data, image, mem_info, memoryOffset, image_state->requirements,
87860ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton                                   image_state->createInfo.tiling == VK_IMAGE_TILING_LINEAR);
87870ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton        }
87880ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton
8789c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton        // Track objects tied to memory
87909b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus        uint64_t image_handle = HandleToUint64(image);
87917a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski        SetMemBinding(dev_data, mem, image_handle, kVulkanObjectTypeImage, "vkBindImageMemory()");
8792c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton
8793341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton        image_state->binding.mem = mem;
8794341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton        image_state->binding.offset = memoryOffset;
8795341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton        image_state->binding.size = image_state->requirements.size;
8796341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton    }
8797341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton}
8798341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton
8799341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort StrattonVKAPI_ATTR VkResult VKAPI_CALL BindImageMemory(VkDevice device, VkImage image, VkDeviceMemory mem, VkDeviceSize memoryOffset) {
8800341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
8801341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
8802160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton    auto image_state = GetImageState(dev_data, image);
8803160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton    bool skip = PreCallValidateBindImageMemory(dev_data, image, image_state, mem, memoryOffset);
8804341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton    if (!skip) {
8805341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton        result = dev_data->dispatch_table.BindImageMemory(device, image, mem, memoryOffset);
8806341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton        if (result == VK_SUCCESS) {
8807160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton            PostCallRecordBindImageMemory(dev_data, image, image_state, mem, memoryOffset);
880894c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis        }
88095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
88105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
88115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
88125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
881389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL SetEvent(VkDevice device, VkEvent event) {
88143251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
88153ee1d6057ee6c49b9dbbeb067b7fd149bdba7b5cTobin Ehlis    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
881656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
8817ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
88189a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto event_state = GetEventNode(dev_data, event);
88194710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis    if (event_state) {
88204710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis        event_state->needsSignaled = false;
88214710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis        event_state->stageMask = VK_PIPELINE_STAGE_HOST_BIT;
88224710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis        if (event_state->write_in_use) {
88233251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT,
88249b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(event), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS",
88253251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "Cannot call vkSetEvent() on event 0x%" PRIxLEAST64 " that is already in use by a command buffer.",
88269b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(event));
88273ee1d6057ee6c49b9dbbeb067b7fd149bdba7b5cTobin Ehlis        }
88283ee1d6057ee6c49b9dbbeb067b7fd149bdba7b5cTobin Ehlis    }
8829b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
88306fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis    // Host setting event is visible to all queues immediately so update stageMask for any queue that's seen this event
88316fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis    // TODO : For correctness this needs separate fix to verify that app doesn't make incorrect assumptions about the
88326fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis    // ordering of this command in relation to vkCmd[Set|Reset]Events (see GH297)
88336fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis    for (auto queue_data : dev_data->queueMap) {
88346fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis        auto event_entry = queue_data.second.eventToStageMap.find(event);
88356fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis        if (event_entry != queue_data.second.eventToStageMap.end()) {
88366fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis            event_entry->second |= VK_PIPELINE_STAGE_HOST_BIT;
88376fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis        }
88386fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis    }
88393251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (!skip) result = dev_data->dispatch_table.SetEvent(device, event);
88405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
88415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
88425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
8843baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardtstatic bool PreCallValidateQueueBindSparse(layer_data *dev_data, VkQueue queue, uint32_t bindInfoCount,
8844baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt                                           const VkBindSparseInfo *pBindInfo, VkFence fence) {
88459a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto pFence = GetFenceNode(dev_data, fence);
8846baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt    bool skip = ValidateFenceForSubmit(dev_data, pFence);
8847baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt    if (skip) {
8848baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt        return true;
8849baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt    }
8850baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt
8851baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt    unordered_set<VkSemaphore> signaled_semaphores;
8852baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt    unordered_set<VkSemaphore> unsignaled_semaphores;
885306d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt    unordered_set<VkSemaphore> internal_semaphores;
8854baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt    for (uint32_t bindIdx = 0; bindIdx < bindInfoCount; ++bindIdx) {
8855baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt        const VkBindSparseInfo &bindInfo = pBindInfo[bindIdx];
8856baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt
8857baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt        std::vector<SEMAPHORE_WAIT> semaphore_waits;
8858baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt        std::vector<VkSemaphore> semaphore_signals;
8859baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt        for (uint32_t i = 0; i < bindInfo.waitSemaphoreCount; ++i) {
8860baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt            VkSemaphore semaphore = bindInfo.pWaitSemaphores[i];
8861baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt            auto pSemaphore = GetSemaphoreNode(dev_data, semaphore);
886206d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt            if (pSemaphore && (pSemaphore->scope == kSyncScopeInternal || internal_semaphores.count(semaphore))) {
8863baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt                if (unsignaled_semaphores.count(semaphore) ||
8864baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt                    (!(signaled_semaphores.count(semaphore)) && !(pSemaphore->signaled))) {
8865baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt                    skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT,
8866baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt                                    HandleToUint64(semaphore), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS",
8867baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt                                    "Queue 0x%p is waiting on semaphore 0x%" PRIx64 " that has no way to be signaled.", queue,
8868baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt                                    HandleToUint64(semaphore));
8869baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt                } else {
8870baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt                    signaled_semaphores.erase(semaphore);
8871baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt                    unsignaled_semaphores.insert(semaphore);
8872baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt                }
8873baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt            }
887406d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt            if (pSemaphore && pSemaphore->scope == kSyncScopeExternalTemporary) {
887506d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                internal_semaphores.insert(semaphore);
887606d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt            }
8877baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt        }
8878baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt        for (uint32_t i = 0; i < bindInfo.signalSemaphoreCount; ++i) {
8879baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt            VkSemaphore semaphore = bindInfo.pSignalSemaphores[i];
8880baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt            auto pSemaphore = GetSemaphoreNode(dev_data, semaphore);
888106d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt            if (pSemaphore && pSemaphore->scope == kSyncScopeInternal) {
8882baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt                if (signaled_semaphores.count(semaphore) || (!(unsignaled_semaphores.count(semaphore)) && pSemaphore->signaled)) {
8883baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt                    skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT,
8884baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt                                    HandleToUint64(semaphore), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS",
8885baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt                                    "Queue 0x%p is signaling semaphore 0x%" PRIx64
8886baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt                                    " that has already been signaled but not waited on by queue 0x%" PRIx64 ".",
8887baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt                                    queue, HandleToUint64(semaphore), HandleToUint64(pSemaphore->signaler.first));
8888baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt                } else {
8889baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt                    unsignaled_semaphores.erase(semaphore);
8890baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt                    signaled_semaphores.insert(semaphore);
8891baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt                }
8892baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt            }
8893baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt        }
8894baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt    }
8895651d92815dfff917308137bb67aacccc4f60df86Chris Forbes
8896baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt    return skip;
8897baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt}
8898baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardtstatic void PostCallRecordQueueBindSparse(layer_data *dev_data, VkQueue queue, uint32_t bindInfoCount,
8899baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt                                          const VkBindSparseInfo *pBindInfo, VkFence fence) {
890085926a33d427ee62f395a50886db980127063c72Mike Schuchardt    uint64_t early_retire_seq = 0;
8901baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt    auto pFence = GetFenceNode(dev_data, fence);
8902baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt    auto pQueue = GetQueueState(dev_data, queue);
8903651d92815dfff917308137bb67aacccc4f60df86Chris Forbes
89046371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt    if (pFence) {
89056371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt        if (pFence->scope == kSyncScopeInternal) {
89066371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt            SubmitFence(pQueue, pFence, std::max(1u, bindInfoCount));
89076371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt            if (!bindInfoCount) {
89086371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt                // No work to do, just dropping a fence in the queue by itself.
89096371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt                pQueue->submissions.emplace_back(std::vector<VkCommandBuffer>(), std::vector<SEMAPHORE_WAIT>(),
89106371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt                                                 std::vector<VkSemaphore>(), std::vector<VkSemaphore>(), fence);
89116371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt            }
89126371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt        } else {
89136371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt            // Retire work up until this fence early, we will not see the wait that corresponds to this signal
89146371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt            early_retire_seq = pQueue->seq + pQueue->submissions.size();
89156371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt            if (!dev_data->external_sync_warning) {
89166371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt                dev_data->external_sync_warning = true;
89176371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt                log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT,
89186371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt                        HandleToUint64(fence), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS",
89196371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt                        "vkQueueBindSparse(): Signaling external fence 0x%" PRIx64 " on queue 0x%" PRIx64
89206371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt                        " will disable validation of preceding command buffer lifecycle states and the in-use status of "
89216371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt                        "associated objects.",
89226371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt                        HandleToUint64(fence), HandleToUint64(queue));
89236371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt            }
89246371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt        }
89254b38d3aa8b6be6a7f5bebb472ab439da0562824fTobin Ehlis    }
8926651d92815dfff917308137bb67aacccc4f60df86Chris Forbes
89271344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis    for (uint32_t bindIdx = 0; bindIdx < bindInfoCount; ++bindIdx) {
89281344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis        const VkBindSparseInfo &bindInfo = pBindInfo[bindIdx];
89295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        // Track objects tied to memory
89301344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis        for (uint32_t j = 0; j < bindInfo.bufferBindCount; j++) {
89311344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis            for (uint32_t k = 0; k < bindInfo.pBufferBinds[j].bindCount; k++) {
8932f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis                auto sparse_binding = bindInfo.pBufferBinds[j].pBinds[k];
8933baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt                SetSparseMemBinding(dev_data, {sparse_binding.memory, sparse_binding.memoryOffset, sparse_binding.size},
8934baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt                                    HandleToUint64(bindInfo.pBufferBinds[j].buffer), kVulkanObjectTypeBuffer);
89355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
89365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
89371344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis        for (uint32_t j = 0; j < bindInfo.imageOpaqueBindCount; j++) {
89381344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis            for (uint32_t k = 0; k < bindInfo.pImageOpaqueBinds[j].bindCount; k++) {
8939f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis                auto sparse_binding = bindInfo.pImageOpaqueBinds[j].pBinds[k];
8940baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt                SetSparseMemBinding(dev_data, {sparse_binding.memory, sparse_binding.memoryOffset, sparse_binding.size},
8941baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt                                    HandleToUint64(bindInfo.pImageOpaqueBinds[j].image), kVulkanObjectTypeImage);
89425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
89435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
89441344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis        for (uint32_t j = 0; j < bindInfo.imageBindCount; j++) {
89451344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis            for (uint32_t k = 0; k < bindInfo.pImageBinds[j].bindCount; k++) {
8946f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis                auto sparse_binding = bindInfo.pImageBinds[j].pBinds[k];
8947f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis                // TODO: This size is broken for non-opaque bindings, need to update to comprehend full sparse binding data
8948f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis                VkDeviceSize size = sparse_binding.extent.depth * sparse_binding.extent.height * sparse_binding.extent.width * 4;
8949baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt                SetSparseMemBinding(dev_data, {sparse_binding.memory, sparse_binding.memoryOffset, size},
8950baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt                                    HandleToUint64(bindInfo.pImageBinds[j].image), kVulkanObjectTypeImage);
89515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
89525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
89539867daedbf52debc77d6568162ee21e071699b80Chris Forbes
89549867daedbf52debc77d6568162ee21e071699b80Chris Forbes        std::vector<SEMAPHORE_WAIT> semaphore_waits;
89559867daedbf52debc77d6568162ee21e071699b80Chris Forbes        std::vector<VkSemaphore> semaphore_signals;
895606d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt        std::vector<VkSemaphore> semaphore_externals;
89571344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis        for (uint32_t i = 0; i < bindInfo.waitSemaphoreCount; ++i) {
895801a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes            VkSemaphore semaphore = bindInfo.pWaitSemaphores[i];
89599a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            auto pSemaphore = GetSemaphoreNode(dev_data, semaphore);
896001a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes            if (pSemaphore) {
896106d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                if (pSemaphore->scope == kSyncScopeInternal) {
896206d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                    if (pSemaphore->signaler.first != VK_NULL_HANDLE) {
896306d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                        semaphore_waits.push_back({semaphore, pSemaphore->signaler.first, pSemaphore->signaler.second});
896406d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                        pSemaphore->in_use.fetch_add(1);
896506d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                    }
896606d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                    pSemaphore->signaler.first = VK_NULL_HANDLE;
896706d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                    pSemaphore->signaled = false;
896806d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                } else {
896906d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                    semaphore_externals.push_back(semaphore);
8970baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt                    pSemaphore->in_use.fetch_add(1);
897106d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                    if (pSemaphore->scope == kSyncScopeExternalTemporary) {
897206d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                        pSemaphore->scope = kSyncScopeInternal;
897306d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                    }
89745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
89755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
89765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
89771344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis        for (uint32_t i = 0; i < bindInfo.signalSemaphoreCount; ++i) {
897801a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes            VkSemaphore semaphore = bindInfo.pSignalSemaphores[i];
89799a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            auto pSemaphore = GetSemaphoreNode(dev_data, semaphore);
898001a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes            if (pSemaphore) {
898106d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                if (pSemaphore->scope == kSyncScopeInternal) {
898206d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                    pSemaphore->signaler.first = queue;
898306d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                    pSemaphore->signaler.second = pQueue->seq + pQueue->submissions.size() + 1;
898406d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                    pSemaphore->signaled = true;
898506d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                    pSemaphore->in_use.fetch_add(1);
898606d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                    semaphore_signals.push_back(semaphore);
898706d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                } else {
898885926a33d427ee62f395a50886db980127063c72Mike Schuchardt                    // Retire work up until this submit early, we will not see the wait that corresponds to this signal
89896371247236bc48772bb4b0ea109fdc400723d84fMike Schuchardt                    early_retire_seq = std::max(early_retire_seq, pQueue->seq + pQueue->submissions.size() + 1);
899085926a33d427ee62f395a50886db980127063c72Mike Schuchardt                    if (!dev_data->external_sync_warning) {
899185926a33d427ee62f395a50886db980127063c72Mike Schuchardt                        dev_data->external_sync_warning = true;
899285926a33d427ee62f395a50886db980127063c72Mike Schuchardt                        log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT,
899385926a33d427ee62f395a50886db980127063c72Mike Schuchardt                                HandleToUint64(semaphore), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS",
899485926a33d427ee62f395a50886db980127063c72Mike Schuchardt                                "vkQueueBindSparse(): Signaling external semaphore 0x%" PRIx64 " on queue 0x%" PRIx64
899585926a33d427ee62f395a50886db980127063c72Mike Schuchardt                                " will disable validation of preceding command buffer lifecycle states and the in-use status of "
899685926a33d427ee62f395a50886db980127063c72Mike Schuchardt                                "associated objects.",
899785926a33d427ee62f395a50886db980127063c72Mike Schuchardt                                HandleToUint64(semaphore), HandleToUint64(queue));
899885926a33d427ee62f395a50886db980127063c72Mike Schuchardt                    }
899906d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                }
90005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
90015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
90029867daedbf52debc77d6568162ee21e071699b80Chris Forbes
900306d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt        pQueue->submissions.emplace_back(std::vector<VkCommandBuffer>(), semaphore_waits, semaphore_signals, semaphore_externals,
90049867daedbf52debc77d6568162ee21e071699b80Chris Forbes                                         bindIdx == bindInfoCount - 1 ? fence : VK_NULL_HANDLE);
90055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
90069867daedbf52debc77d6568162ee21e071699b80Chris Forbes
900785926a33d427ee62f395a50886db980127063c72Mike Schuchardt    if (early_retire_seq) {
900885926a33d427ee62f395a50886db980127063c72Mike Schuchardt        RetireWorkOnQueue(dev_data, pQueue, early_retire_seq);
900985926a33d427ee62f395a50886db980127063c72Mike Schuchardt    }
9010baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt}
90119867daedbf52debc77d6568162ee21e071699b80Chris Forbes
9012baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike SchuchardtVKAPI_ATTR VkResult VKAPI_CALL QueueBindSparse(VkQueue queue, uint32_t bindInfoCount, const VkBindSparseInfo *pBindInfo,
9013baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt                                               VkFence fence) {
9014baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map);
9015baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt    unique_lock_t lock(global_lock);
9016baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt    bool skip = PreCallValidateQueueBindSparse(dev_data, queue, bindInfoCount, pBindInfo, fence);
9017b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
90185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
9019baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt    if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
9020baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt
9021baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt    VkResult result = dev_data->dispatch_table.QueueBindSparse(queue, bindInfoCount, pBindInfo, fence);
90225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
9023baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt    lock.lock();
9024baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt    PostCallRecordQueueBindSparse(dev_data, queue, bindInfoCount, pBindInfo, fence);
9025baf4a700b1d8e70ac34d8f8069f5eb496efae0dfMike Schuchardt    lock.unlock();
90265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
90275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
90285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
902989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateSemaphore(VkDevice device, const VkSemaphoreCreateInfo *pCreateInfo,
903089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                               const VkAllocationCallbacks *pAllocator, VkSemaphore *pSemaphore) {
903156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
90324a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.CreateSemaphore(device, pCreateInfo, pAllocator, pSemaphore);
90335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (result == VK_SUCCESS) {
9034ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes        lock_guard_t lock(global_lock);
9035bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        SEMAPHORE_NODE *sNode = &dev_data->semaphoreMap[*pSemaphore];
90369867daedbf52debc77d6568162ee21e071699b80Chris Forbes        sNode->signaler.first = VK_NULL_HANDLE;
90379867daedbf52debc77d6568162ee21e071699b80Chris Forbes        sNode->signaler.second = 0;
90381344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis        sNode->signaled = false;
903906d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt        sNode->scope = kSyncScopeInternal;
90405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
90415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
90425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
90435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
904406d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardtstatic bool PreCallValidateImportSemaphore(layer_data *dev_data, VkSemaphore semaphore, const char *caller_name) {
904506d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt    SEMAPHORE_NODE *sema_node = GetSemaphoreNode(dev_data, semaphore);
904606d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt    VK_OBJECT obj_struct = {HandleToUint64(semaphore), kVulkanObjectTypeSemaphore};
904706d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt    bool skip = false;
904806d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt    if (sema_node) {
904906d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt        skip |= ValidateObjectNotInUse(dev_data, sema_node, obj_struct, caller_name, VALIDATION_ERROR_UNDEFINED);
905006d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt    }
905106d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt    return skip;
905206d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt}
905306d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt
905406d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardtstatic void PostCallRecordImportSemaphore(layer_data *dev_data, VkSemaphore semaphore,
905506d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                                          VkExternalSemaphoreHandleTypeFlagBitsKHR handle_type, VkSemaphoreImportFlagsKHR flags) {
905606d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt    SEMAPHORE_NODE *sema_node = GetSemaphoreNode(dev_data, semaphore);
905706d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt    if (sema_node && sema_node->scope != kSyncScopeExternalPermanent) {
905806d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt        if ((handle_type == VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR || flags & VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR) &&
905906d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt            sema_node->scope == kSyncScopeInternal) {
906006d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt            sema_node->scope = kSyncScopeExternalTemporary;
906106d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt        } else {
906206d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt            sema_node->scope = kSyncScopeExternalPermanent;
906306d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt        }
906406d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt    }
906506d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt}
906606d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt
906706d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt#ifdef VK_USE_PLATFORM_WIN32_KHR
906806d5c171f0bb0acbed8120af6bac43f13a869e3fMike SchuchardtVKAPI_ATTR VkResult VKAPI_CALL
906906d5c171f0bb0acbed8120af6bac43f13a869e3fMike SchuchardtImportSemaphoreWin32HandleKHR(VkDevice device, const VkImportSemaphoreWin32HandleInfoKHR *pImportSemaphoreWin32HandleInfo) {
907006d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
907106d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
907206d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt    bool skip =
907306d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt        PreCallValidateImportSemaphore(dev_data, pImportSemaphoreWin32HandleInfo->semaphore, "vkImportSemaphoreWin32HandleKHR");
907406d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt
907506d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt    if (!skip) {
907606d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt        result = dev_data->dispatch_table.ImportSemaphoreWin32HandleKHR(device, pImportSemaphoreWin32HandleInfo);
907706d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt    }
907806d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt
907906d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt    if (result == VK_SUCCESS) {
908006d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt        PostCallRecordImportSemaphore(dev_data, pImportSemaphoreWin32HandleInfo->semaphore,
908106d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                                      pImportSemaphoreWin32HandleInfo->handleType, pImportSemaphoreWin32HandleInfo->flags);
908206d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt    }
908306d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt    return result;
908406d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt}
908506d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt#endif
908606d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt
908716f39f23c20176b9ff809d10d76b62663e1adabdMike SchuchardtVKAPI_ATTR VkResult VKAPI_CALL ImportSemaphoreFdKHR(VkDevice device, const VkImportSemaphoreFdInfoKHR *pImportSemaphoreFdInfo) {
908816f39f23c20176b9ff809d10d76b62663e1adabdMike Schuchardt    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
908916f39f23c20176b9ff809d10d76b62663e1adabdMike Schuchardt    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
909016f39f23c20176b9ff809d10d76b62663e1adabdMike Schuchardt    bool skip = PreCallValidateImportSemaphore(dev_data, pImportSemaphoreFdInfo->semaphore, "vkImportSemaphoreFdKHR");
909116f39f23c20176b9ff809d10d76b62663e1adabdMike Schuchardt
909216f39f23c20176b9ff809d10d76b62663e1adabdMike Schuchardt    if (!skip) {
909316f39f23c20176b9ff809d10d76b62663e1adabdMike Schuchardt        result = dev_data->dispatch_table.ImportSemaphoreFdKHR(device, pImportSemaphoreFdInfo);
909416f39f23c20176b9ff809d10d76b62663e1adabdMike Schuchardt    }
909516f39f23c20176b9ff809d10d76b62663e1adabdMike Schuchardt
909616f39f23c20176b9ff809d10d76b62663e1adabdMike Schuchardt    if (result == VK_SUCCESS) {
909716f39f23c20176b9ff809d10d76b62663e1adabdMike Schuchardt        PostCallRecordImportSemaphore(dev_data, pImportSemaphoreFdInfo->semaphore, pImportSemaphoreFdInfo->handleType,
909816f39f23c20176b9ff809d10d76b62663e1adabdMike Schuchardt                                      pImportSemaphoreFdInfo->flags);
909916f39f23c20176b9ff809d10d76b62663e1adabdMike Schuchardt    }
910016f39f23c20176b9ff809d10d76b62663e1adabdMike Schuchardt    return result;
910116f39f23c20176b9ff809d10d76b62663e1adabdMike Schuchardt}
910216f39f23c20176b9ff809d10d76b62663e1adabdMike Schuchardt
910306d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardtstatic void PostCallRecordGetSemaphore(layer_data *dev_data, VkSemaphore semaphore,
910406d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                                       VkExternalSemaphoreHandleTypeFlagBitsKHR handle_type) {
910506d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt    SEMAPHORE_NODE *sema_node = GetSemaphoreNode(dev_data, semaphore);
910606d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt    if (sema_node && handle_type != VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR) {
910706d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt        // Cannot track semaphore state once it is exported, except for Sync FD handle types which have copy transference
910806d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt        sema_node->scope = kSyncScopeExternalPermanent;
910906d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt    }
911006d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt}
911106d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt
911206d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt#ifdef VK_USE_PLATFORM_WIN32_KHR
911306d5c171f0bb0acbed8120af6bac43f13a869e3fMike SchuchardtVKAPI_ATTR VkResult VKAPI_CALL GetSemaphoreWin32HandleKHR(VkDevice device,
911406d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                                                          const VkSemaphoreGetWin32HandleInfoKHR *pGetWin32HandleInfo,
911506d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt                                                          HANDLE *pHandle) {
911606d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
911706d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt    VkResult result = dev_data->dispatch_table.GetSemaphoreWin32HandleKHR(device, pGetWin32HandleInfo, pHandle);
911806d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt
911906d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt    if (result == VK_SUCCESS) {
912006d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt        PostCallRecordGetSemaphore(dev_data, pGetWin32HandleInfo->semaphore, pGetWin32HandleInfo->handleType);
912106d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt    }
912206d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt    return result;
912306d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt}
912406d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt#endif
912506d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt
912616f39f23c20176b9ff809d10d76b62663e1adabdMike SchuchardtVKAPI_ATTR VkResult VKAPI_CALL GetSemaphoreFdKHR(VkDevice device, const VkSemaphoreGetFdInfoKHR *pGetFdInfo, int *pFd) {
912716f39f23c20176b9ff809d10d76b62663e1adabdMike Schuchardt    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
912816f39f23c20176b9ff809d10d76b62663e1adabdMike Schuchardt    VkResult result = dev_data->dispatch_table.GetSemaphoreFdKHR(device, pGetFdInfo, pFd);
912916f39f23c20176b9ff809d10d76b62663e1adabdMike Schuchardt
913016f39f23c20176b9ff809d10d76b62663e1adabdMike Schuchardt    if (result == VK_SUCCESS) {
913116f39f23c20176b9ff809d10d76b62663e1adabdMike Schuchardt        PostCallRecordGetSemaphore(dev_data, pGetFdInfo->semaphore, pGetFdInfo->handleType);
913216f39f23c20176b9ff809d10d76b62663e1adabdMike Schuchardt    }
913316f39f23c20176b9ff809d10d76b62663e1adabdMike Schuchardt    return result;
913416f39f23c20176b9ff809d10d76b62663e1adabdMike Schuchardt}
913516f39f23c20176b9ff809d10d76b62663e1adabdMike Schuchardt
9136804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardtstatic bool PreCallValidateImportFence(layer_data *dev_data, VkFence fence, const char *caller_name) {
9137804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt    FENCE_NODE *fence_node = GetFenceNode(dev_data, fence);
9138804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt    bool skip = false;
9139804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt    if (fence_node && fence_node->scope == kSyncScopeInternal && fence_node->state == FENCE_INFLIGHT) {
9140804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT,
9141804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt                        HandleToUint64(fence), __LINE__, VALIDATION_ERROR_UNDEFINED, "DS",
9142804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt                        "Cannot call %s on fence 0x%" PRIx64 " that is currently in use.", caller_name, HandleToUint64(fence));
9143804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt    }
9144804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt    return skip;
9145804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt}
9146804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt
9147804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardtstatic void PostCallRecordImportFence(layer_data *dev_data, VkFence fence, VkExternalFenceHandleTypeFlagBitsKHR handle_type,
9148804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt                                      VkFenceImportFlagsKHR flags) {
9149804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt    FENCE_NODE *fence_node = GetFenceNode(dev_data, fence);
9150804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt    if (fence_node && fence_node->scope != kSyncScopeExternalPermanent) {
9151804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt        if ((handle_type == VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR || flags & VK_FENCE_IMPORT_TEMPORARY_BIT_KHR) &&
9152804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt            fence_node->scope == kSyncScopeInternal) {
9153804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt            fence_node->scope = kSyncScopeExternalTemporary;
9154804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt        } else {
9155804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt            fence_node->scope = kSyncScopeExternalPermanent;
9156804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt        }
9157804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt    }
9158804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt}
9159804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt
9160804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt#ifdef VK_USE_PLATFORM_WIN32_KHR
9161804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike SchuchardtVKAPI_ATTR VkResult VKAPI_CALL ImportFenceWin32HandleKHR(VkDevice device,
9162804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt                                                         const VkImportFenceWin32HandleInfoKHR *pImportFenceWin32HandleInfo) {
9163804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
9164804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
9165804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt    bool skip = PreCallValidateImportFence(dev_data, pImportFenceWin32HandleInfo->fence, "vkImportFenceWin32HandleKHR");
9166804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt
9167804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt    if (!skip) {
9168804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt        result = dev_data->dispatch_table.ImportFenceWin32HandleKHR(device, pImportFenceWin32HandleInfo);
9169804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt    }
9170804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt
9171804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt    if (result == VK_SUCCESS) {
9172804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt        PostCallRecordImportFence(dev_data, pImportFenceWin32HandleInfo->fence, pImportFenceWin32HandleInfo->handleType,
9173804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt                                  pImportFenceWin32HandleInfo->flags);
9174804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt    }
9175804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt    return result;
9176804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt}
9177804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt#endif
9178804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt
9179804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike SchuchardtVKAPI_ATTR VkResult VKAPI_CALL ImportFenceFdKHR(VkDevice device, const VkImportFenceFdInfoKHR *pImportFenceFdInfo) {
9180804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
9181804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
9182804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt    bool skip = PreCallValidateImportFence(dev_data, pImportFenceFdInfo->fence, "vkImportFenceFdKHR");
9183804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt
9184804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt    if (!skip) {
9185804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt        result = dev_data->dispatch_table.ImportFenceFdKHR(device, pImportFenceFdInfo);
9186804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt    }
9187804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt
9188804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt    if (result == VK_SUCCESS) {
9189804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt        PostCallRecordImportFence(dev_data, pImportFenceFdInfo->fence, pImportFenceFdInfo->handleType, pImportFenceFdInfo->flags);
9190804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt    }
9191804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt    return result;
9192804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt}
9193804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt
9194804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardtstatic void PostCallRecordGetFence(layer_data *dev_data, VkFence fence, VkExternalFenceHandleTypeFlagBitsKHR handle_type) {
9195804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt    FENCE_NODE *fence_node = GetFenceNode(dev_data, fence);
9196804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt    if (fence_node) {
9197804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt        if (handle_type != VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR) {
9198804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt            // Export with reference transference becomes external
9199804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt            fence_node->scope = kSyncScopeExternalPermanent;
9200804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt        } else if (fence_node->scope == kSyncScopeInternal) {
9201804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt            // Export with copy transference has a side effect of resetting the fence
9202804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt            fence_node->state = FENCE_UNSIGNALED;
9203804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt        }
9204804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt    }
9205804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt}
9206804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt
9207804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt#ifdef VK_USE_PLATFORM_WIN32_KHR
9208804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike SchuchardtVKAPI_ATTR VkResult VKAPI_CALL GetFenceWin32HandleKHR(VkDevice device, const VkFenceGetWin32HandleInfoKHR *pGetWin32HandleInfo,
9209804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt                                                      HANDLE *pHandle) {
9210804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
9211804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt    VkResult result = dev_data->dispatch_table.GetFenceWin32HandleKHR(device, pGetWin32HandleInfo, pHandle);
9212804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt
9213804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt    if (result == VK_SUCCESS) {
9214804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt        PostCallRecordGetFence(dev_data, pGetWin32HandleInfo->fence, pGetWin32HandleInfo->handleType);
9215804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt    }
9216804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt    return result;
9217804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt}
9218804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt#endif
9219804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt
9220804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike SchuchardtVKAPI_ATTR VkResult VKAPI_CALL GetFenceFdKHR(VkDevice device, const VkFenceGetFdInfoKHR *pGetFdInfo, int *pFd) {
9221804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
9222804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt    VkResult result = dev_data->dispatch_table.GetFenceFdKHR(device, pGetFdInfo, pFd);
9223804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt
9224804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt    if (result == VK_SUCCESS) {
9225804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt        PostCallRecordGetFence(dev_data, pGetFdInfo->fence, pGetFdInfo->handleType);
9226804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt    }
9227804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt    return result;
9228804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt}
9229804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt
9230bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateEvent(VkDevice device, const VkEventCreateInfo *pCreateInfo,
9231bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                           const VkAllocationCallbacks *pAllocator, VkEvent *pEvent) {
923256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
92334a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.CreateEvent(device, pCreateInfo, pAllocator, pEvent);
92345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (result == VK_SUCCESS) {
9235ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes        lock_guard_t lock(global_lock);
92365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        dev_data->eventMap[*pEvent].needsSignaled = false;
9237293ecfc5e69ed3978a8c04518166d828294870a4Tony Barbour        dev_data->eventMap[*pEvent].write_in_use = 0;
92385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        dev_data->eventMap[*pEvent].stageMask = VkPipelineStageFlags(0);
92395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
92405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
92415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
92425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
92439ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinskistatic bool PreCallValidateCreateSwapchainKHR(layer_data *dev_data, const char *func_name,
92449ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                                              VkSwapchainCreateInfoKHR const *pCreateInfo, SURFACE_STATE *surface_state,
92459ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                                              SWAPCHAIN_NODE *old_swapchain_state) {
9246d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes    auto most_recent_swapchain = surface_state->swapchain ? surface_state->swapchain : surface_state->old_swapchain;
9247d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes
92484bd5f453535de3d3423ff1f9995b4acb15f791d2Chris Forbes    // TODO: revisit this. some of these rules are being relaxed.
92490bbc015828bdb99e85e6731ce92428557902701fPetr Kraus
92500bbc015828bdb99e85e6731ce92428557902701fPetr Kraus    // All physical devices and queue families are required to be able
92510bbc015828bdb99e85e6731ce92428557902701fPetr Kraus    // to present to any native window on Android; require the
92520bbc015828bdb99e85e6731ce92428557902701fPetr Kraus    // application to have established support on any other platform.
9253d4eaca34eca7f4b4e34190c441a579347bb2016aMark Lobodzinski    if (!dev_data->instance_data->extensions.vk_khr_android_surface) {
92540bbc015828bdb99e85e6731ce92428557902701fPetr Kraus        auto support_predicate = [dev_data](decltype(surface_state->gpu_queue_support)::const_reference qs) -> bool {
92550bbc015828bdb99e85e6731ce92428557902701fPetr Kraus            // TODO: should restrict search only to queue families of VkDeviceQueueCreateInfos, not whole phys. device
92560bbc015828bdb99e85e6731ce92428557902701fPetr Kraus            return (qs.first.gpu == dev_data->physical_device) && qs.second;
92570bbc015828bdb99e85e6731ce92428557902701fPetr Kraus        };
92580bbc015828bdb99e85e6731ce92428557902701fPetr Kraus        const auto& support = surface_state->gpu_queue_support;
92590bbc015828bdb99e85e6731ce92428557902701fPetr Kraus        bool is_supported = std::any_of(support.begin(), support.end(), support_predicate);
92600bbc015828bdb99e85e6731ce92428557902701fPetr Kraus
92610bbc015828bdb99e85e6731ce92428557902701fPetr Kraus        if (!is_supported) {
92620bbc015828bdb99e85e6731ce92428557902701fPetr Kraus            if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
9263315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(dev_data->device), __LINE__, VALIDATION_ERROR_146009ec, "DS",
92640bbc015828bdb99e85e6731ce92428557902701fPetr Kraus                        "%s: pCreateInfo->surface is not known at this time to be supported for presentation by this device. "
92650bbc015828bdb99e85e6731ce92428557902701fPetr Kraus                        "The vkGetPhysicalDeviceSurfaceSupportKHR() must be called beforehand, and it must return VK_TRUE support "
92660bbc015828bdb99e85e6731ce92428557902701fPetr Kraus                        "with this surface for at least one queue family of this device. %s",
9267315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        func_name, validation_error_map[VALIDATION_ERROR_146009ec]))
92680bbc015828bdb99e85e6731ce92428557902701fPetr Kraus                return true;
92690bbc015828bdb99e85e6731ce92428557902701fPetr Kraus        }
92700bbc015828bdb99e85e6731ce92428557902701fPetr Kraus    }
92710bbc015828bdb99e85e6731ce92428557902701fPetr Kraus
9272d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes    if (most_recent_swapchain != old_swapchain_state || (surface_state->old_swapchain && surface_state->swapchain)) {
9273d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes        if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
92749b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                    HandleToUint64(dev_data->device), __LINE__, DRAWSTATE_SWAPCHAIN_ALREADY_EXISTS, "DS",
92759ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                    "%s: surface has an existing swapchain other than oldSwapchain", func_name))
9276d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes            return true;
9277d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes    }
9278d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes    if (old_swapchain_state && old_swapchain_state->createInfo.surface != pCreateInfo->surface) {
9279d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes        if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
92809b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                    HandleToUint64(pCreateInfo->oldSwapchain), __LINE__, DRAWSTATE_SWAPCHAIN_WRONG_SURFACE, "DS",
92819b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                    "%s: pCreateInfo->oldSwapchain's surface is not pCreateInfo->surface", func_name))
9282d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes            return true;
9283d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes    }
92849a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto physical_device_state = GetPhysicalDeviceState(dev_data->instance_data, dev_data->physical_device);
92857de258f87ca1192db116a66b209253793d276ebcChris Forbes    if (physical_device_state->vkGetPhysicalDeviceSurfaceCapabilitiesKHRState == UNCALLED) {
92867de258f87ca1192db116a66b209253793d276ebcChris Forbes        if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
92879b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                    HandleToUint64(dev_data->physical_device), __LINE__, DRAWSTATE_SWAPCHAIN_CREATE_BEFORE_QUERY, "DS",
92889ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                    "%s: surface capabilities not retrieved for this physical device", func_name))
92897de258f87ca1192db116a66b209253793d276ebcChris Forbes            return true;
9290cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    } else {  // have valid capabilities
92915c99b4daed164798f307244c9bde17b4f66014fbChris Forbes        auto &capabilities = physical_device_state->surfaceCapabilities;
92929ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski        // Validate pCreateInfo->minImageCount against VkSurfaceCapabilitiesKHR::{min|max}ImageCount:
92932fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen        if (pCreateInfo->minImageCount < capabilities.minImageCount) {
92942fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen            if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
9295315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(dev_data->device), __LINE__, VALIDATION_ERROR_146009ee, "DS",
92969ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                        "%s called with minImageCount = %d, which is outside the bounds returned "
92972fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen                        "by vkGetPhysicalDeviceSurfaceCapabilitiesKHR() (i.e. minImageCount = %d, maxImageCount = %d). %s",
92989ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                        func_name, pCreateInfo->minImageCount, capabilities.minImageCount, capabilities.maxImageCount,
9299315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_146009ee]))
93002fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen                return true;
93012fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen        }
93022fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen
93032fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen        if ((capabilities.maxImageCount > 0) && (pCreateInfo->minImageCount > capabilities.maxImageCount)) {
93045c99b4daed164798f307244c9bde17b4f66014fbChris Forbes            if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
9305315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(dev_data->device), __LINE__, VALIDATION_ERROR_146009f0, "DS",
93069ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                        "%s called with minImageCount = %d, which is outside the bounds returned "
93072fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen                        "by vkGetPhysicalDeviceSurfaceCapabilitiesKHR() (i.e. minImageCount = %d, maxImageCount = %d). %s",
93089ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                        func_name, pCreateInfo->minImageCount, capabilities.minImageCount, capabilities.maxImageCount,
9309315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_146009f0]))
93105c99b4daed164798f307244c9bde17b4f66014fbChris Forbes                return true;
93115c99b4daed164798f307244c9bde17b4f66014fbChris Forbes        }
93122fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen
93139ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski        // Validate pCreateInfo->imageExtent against VkSurfaceCapabilitiesKHR::{current|min|max}ImageExtent:
9314b42b2f0f35df5143dcc982217434cf0d42a45afeCort        if ((pCreateInfo->imageExtent.width < capabilities.minImageExtent.width) ||
9315b42b2f0f35df5143dcc982217434cf0d42a45afeCort            (pCreateInfo->imageExtent.width > capabilities.maxImageExtent.width) ||
9316b42b2f0f35df5143dcc982217434cf0d42a45afeCort            (pCreateInfo->imageExtent.height < capabilities.minImageExtent.height) ||
9317b42b2f0f35df5143dcc982217434cf0d42a45afeCort            (pCreateInfo->imageExtent.height > capabilities.maxImageExtent.height)) {
93185c99b4daed164798f307244c9bde17b4f66014fbChris Forbes            if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
9319315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(dev_data->device), __LINE__, VALIDATION_ERROR_146009f4, "DS",
93209ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                        "%s called with imageExtent = (%d,%d), which is outside the bounds returned by "
93219ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                        "vkGetPhysicalDeviceSurfaceCapabilitiesKHR(): currentExtent = (%d,%d), minImageExtent = (%d,%d), "
93229ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                        "maxImageExtent = (%d,%d). %s",
93239ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                        func_name, pCreateInfo->imageExtent.width, pCreateInfo->imageExtent.height,
93249ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                        capabilities.currentExtent.width, capabilities.currentExtent.height, capabilities.minImageExtent.width,
93259ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                        capabilities.minImageExtent.height, capabilities.maxImageExtent.width, capabilities.maxImageExtent.height,
9326315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_146009f4]))
93275c99b4daed164798f307244c9bde17b4f66014fbChris Forbes                return true;
93285c99b4daed164798f307244c9bde17b4f66014fbChris Forbes        }
93299ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski        // pCreateInfo->preTransform should have exactly one bit set, and that bit must also be set in
93309ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski        // VkSurfaceCapabilitiesKHR::supportedTransforms.
93315c99b4daed164798f307244c9bde17b4f66014fbChris Forbes        if (!pCreateInfo->preTransform || (pCreateInfo->preTransform & (pCreateInfo->preTransform - 1)) ||
93325c99b4daed164798f307244c9bde17b4f66014fbChris Forbes            !(pCreateInfo->preTransform & capabilities.supportedTransforms)) {
93339ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski            // This is an error situation; one for which we'd like to give the developer a helpful, multi-line error message.  Build
93349ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski            // it up a little at a time, and then log it:
93355c99b4daed164798f307244c9bde17b4f66014fbChris Forbes            std::string errorString = "";
93365c99b4daed164798f307244c9bde17b4f66014fbChris Forbes            char str[1024];
93375c99b4daed164798f307244c9bde17b4f66014fbChris Forbes            // Here's the first part of the message:
93389ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski            sprintf(str, "%s called with a non-supported pCreateInfo->preTransform (i.e. %s).  Supported values are:\n", func_name,
93395c99b4daed164798f307244c9bde17b4f66014fbChris Forbes                    string_VkSurfaceTransformFlagBitsKHR(pCreateInfo->preTransform));
93405c99b4daed164798f307244c9bde17b4f66014fbChris Forbes            errorString += str;
93415c99b4daed164798f307244c9bde17b4f66014fbChris Forbes            for (int i = 0; i < 32; i++) {
93425c99b4daed164798f307244c9bde17b4f66014fbChris Forbes                // Build up the rest of the message:
93435c99b4daed164798f307244c9bde17b4f66014fbChris Forbes                if ((1 << i) & capabilities.supportedTransforms) {
93445c99b4daed164798f307244c9bde17b4f66014fbChris Forbes                    const char *newStr = string_VkSurfaceTransformFlagBitsKHR((VkSurfaceTransformFlagBitsKHR)(1 << i));
93455c99b4daed164798f307244c9bde17b4f66014fbChris Forbes                    sprintf(str, "    %s\n", newStr);
93465c99b4daed164798f307244c9bde17b4f66014fbChris Forbes                    errorString += str;
93475c99b4daed164798f307244c9bde17b4f66014fbChris Forbes                }
93485c99b4daed164798f307244c9bde17b4f66014fbChris Forbes            }
93495c99b4daed164798f307244c9bde17b4f66014fbChris Forbes            // Log the message that we've built up:
93505c99b4daed164798f307244c9bde17b4f66014fbChris Forbes            if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
9351315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(dev_data->device), __LINE__, VALIDATION_ERROR_146009fe, "DS", "%s. %s", errorString.c_str(),
9352315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_146009fe]))
93535c99b4daed164798f307244c9bde17b4f66014fbChris Forbes                return true;
93545c99b4daed164798f307244c9bde17b4f66014fbChris Forbes        }
93557b0d28d116977b91892f354e002edd760bdb86cbChris Forbes
93569ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski        // pCreateInfo->compositeAlpha should have exactly one bit set, and that bit must also be set in
93579ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski        // VkSurfaceCapabilitiesKHR::supportedCompositeAlpha
93585c99b4daed164798f307244c9bde17b4f66014fbChris Forbes        if (!pCreateInfo->compositeAlpha || (pCreateInfo->compositeAlpha & (pCreateInfo->compositeAlpha - 1)) ||
93595c99b4daed164798f307244c9bde17b4f66014fbChris Forbes            !((pCreateInfo->compositeAlpha) & capabilities.supportedCompositeAlpha)) {
93609ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski            // This is an error situation; one for which we'd like to give the developer a helpful, multi-line error message.  Build
93619ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski            // it up a little at a time, and then log it:
93625c99b4daed164798f307244c9bde17b4f66014fbChris Forbes            std::string errorString = "";
93635c99b4daed164798f307244c9bde17b4f66014fbChris Forbes            char str[1024];
93645c99b4daed164798f307244c9bde17b4f66014fbChris Forbes            // Here's the first part of the message:
93659ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski            sprintf(str, "%s called with a non-supported pCreateInfo->compositeAlpha (i.e. %s).  Supported values are:\n",
93669ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                    func_name, string_VkCompositeAlphaFlagBitsKHR(pCreateInfo->compositeAlpha));
93675c99b4daed164798f307244c9bde17b4f66014fbChris Forbes            errorString += str;
93685c99b4daed164798f307244c9bde17b4f66014fbChris Forbes            for (int i = 0; i < 32; i++) {
93695c99b4daed164798f307244c9bde17b4f66014fbChris Forbes                // Build up the rest of the message:
93705c99b4daed164798f307244c9bde17b4f66014fbChris Forbes                if ((1 << i) & capabilities.supportedCompositeAlpha) {
93715c99b4daed164798f307244c9bde17b4f66014fbChris Forbes                    const char *newStr = string_VkCompositeAlphaFlagBitsKHR((VkCompositeAlphaFlagBitsKHR)(1 << i));
93725c99b4daed164798f307244c9bde17b4f66014fbChris Forbes                    sprintf(str, "    %s\n", newStr);
93735c99b4daed164798f307244c9bde17b4f66014fbChris Forbes                    errorString += str;
93745c99b4daed164798f307244c9bde17b4f66014fbChris Forbes                }
93755c99b4daed164798f307244c9bde17b4f66014fbChris Forbes            }
93765c99b4daed164798f307244c9bde17b4f66014fbChris Forbes            // Log the message that we've built up:
93775c99b4daed164798f307244c9bde17b4f66014fbChris Forbes            if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
9378315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(dev_data->device), __LINE__, VALIDATION_ERROR_14600a00, "DS", "%s. %s", errorString.c_str(),
9379315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_14600a00]))
93805c99b4daed164798f307244c9bde17b4f66014fbChris Forbes                return true;
93815c99b4daed164798f307244c9bde17b4f66014fbChris Forbes        }
93829ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski        // Validate pCreateInfo->imageArrayLayers against VkSurfaceCapabilitiesKHR::maxImageArrayLayers:
93835c99b4daed164798f307244c9bde17b4f66014fbChris Forbes        if ((pCreateInfo->imageArrayLayers < 1) || (pCreateInfo->imageArrayLayers > capabilities.maxImageArrayLayers)) {
93845c99b4daed164798f307244c9bde17b4f66014fbChris Forbes            if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
9385315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(dev_data->device), __LINE__, VALIDATION_ERROR_146009f6, "DS",
93869ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                        "%s called with a non-supported imageArrayLayers (i.e. %d).  Minimum value is 1, maximum value is %d. %s",
93879ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                        func_name, pCreateInfo->imageArrayLayers, capabilities.maxImageArrayLayers,
9388315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_146009f6]))
93895c99b4daed164798f307244c9bde17b4f66014fbChris Forbes                return true;
93905c99b4daed164798f307244c9bde17b4f66014fbChris Forbes        }
93919ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski        // Validate pCreateInfo->imageUsage against VkSurfaceCapabilitiesKHR::supportedUsageFlags:
93925c99b4daed164798f307244c9bde17b4f66014fbChris Forbes        if (pCreateInfo->imageUsage != (pCreateInfo->imageUsage & capabilities.supportedUsageFlags)) {
93935c99b4daed164798f307244c9bde17b4f66014fbChris Forbes            if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
9394315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(dev_data->device), __LINE__, VALIDATION_ERROR_146009f8, "DS",
93959ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                        "%s called with a non-supported pCreateInfo->imageUsage (i.e. 0x%08x).  Supported flag bits are 0x%08x. %s",
93969ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                        func_name, pCreateInfo->imageUsage, capabilities.supportedUsageFlags,
9397315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_146009f8]))
93985c99b4daed164798f307244c9bde17b4f66014fbChris Forbes                return true;
93995c99b4daed164798f307244c9bde17b4f66014fbChris Forbes        }
94007de258f87ca1192db116a66b209253793d276ebcChris Forbes    }
9401d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes
94029ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski    // Validate pCreateInfo values with the results of vkGetPhysicalDeviceSurfaceFormatsKHR():
94035faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes    if (physical_device_state->vkGetPhysicalDeviceSurfaceFormatsKHRState != QUERY_DETAILS) {
94045faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes        if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
94059b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                    HandleToUint64(dev_data->device), __LINE__, DRAWSTATE_SWAPCHAIN_CREATE_BEFORE_QUERY, "DS",
94069ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                    "%s called before calling vkGetPhysicalDeviceSurfaceFormatsKHR().", func_name))
94075faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes            return true;
94085faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes    } else {
94099ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski        // Validate pCreateInfo->imageFormat against VkSurfaceFormatKHR::format:
94105faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes        bool foundFormat = false;
94115faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes        bool foundColorSpace = false;
94125faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes        bool foundMatch = false;
94135faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes        for (auto const &format : physical_device_state->surface_formats) {
94145faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes            if (pCreateInfo->imageFormat == format.format) {
94159ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                // Validate pCreateInfo->imageColorSpace against VkSurfaceFormatKHR::colorSpace:
94165faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes                foundFormat = true;
94175faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes                if (pCreateInfo->imageColorSpace == format.colorSpace) {
94185faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes                    foundMatch = true;
94195faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes                    break;
94205faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes                }
94215faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes            } else {
94225faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes                if (pCreateInfo->imageColorSpace == format.colorSpace) {
94235faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes                    foundColorSpace = true;
94245faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes                }
94255faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes            }
94265faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes        }
94275faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes        if (!foundMatch) {
94285faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes            if (!foundFormat) {
94295faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes                if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
9430315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(dev_data->device), __LINE__, VALIDATION_ERROR_146009f2, "DS",
9431bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                            "%s called with a non-supported pCreateInfo->imageFormat (i.e. %d). %s", func_name,
9432315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            pCreateInfo->imageFormat, validation_error_map[VALIDATION_ERROR_146009f2]))
94332fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen                    return true;
94342fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen            }
94352fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen            if (!foundColorSpace) {
94362fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen                if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
9437315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            HandleToUint64(dev_data->device), __LINE__, VALIDATION_ERROR_146009f2, "DS",
9438bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                            "%s called with a non-supported pCreateInfo->imageColorSpace (i.e. %d). %s", func_name,
9439315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                            pCreateInfo->imageColorSpace, validation_error_map[VALIDATION_ERROR_146009f2]))
94405faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes                    return true;
94415faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes            }
94425faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes        }
94435faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes    }
94445faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes
94459ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski    // Validate pCreateInfo values with the results of vkGetPhysicalDeviceSurfacePresentModesKHR():
94469e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes    if (physical_device_state->vkGetPhysicalDeviceSurfacePresentModesKHRState != QUERY_DETAILS) {
944725002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski        // FIFO is required to always be supported
94489e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes        if (pCreateInfo->presentMode != VK_PRESENT_MODE_FIFO_KHR) {
94499e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes            if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
94509b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        HandleToUint64(dev_data->device), __LINE__, DRAWSTATE_SWAPCHAIN_CREATE_BEFORE_QUERY, "DS",
94519ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                        "%s called before calling vkGetPhysicalDeviceSurfacePresentModesKHR().", func_name))
94529e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes                return true;
94539e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes        }
94549e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes    } else {
94559ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski        // Validate pCreateInfo->presentMode against vkGetPhysicalDeviceSurfacePresentModesKHR():
9456bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        bool foundMatch = std::find(physical_device_state->present_modes.begin(), physical_device_state->present_modes.end(),
94579e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes                                    pCreateInfo->presentMode) != physical_device_state->present_modes.end();
94589e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes        if (!foundMatch) {
94599e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes            if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
9460315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(dev_data->device), __LINE__, VALIDATION_ERROR_14600a02, "DS",
94619ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski                        "%s called with a non-supported presentMode (i.e. %s). %s", func_name,
9462315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        string_VkPresentModeKHR(pCreateInfo->presentMode), validation_error_map[VALIDATION_ERROR_14600a02]))
94639e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes                return true;
94649e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes        }
94659e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes    }
946687a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis    // Validate state for shared presentable case
946787a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis    if (VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR == pCreateInfo->presentMode ||
946887a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis        VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR == pCreateInfo->presentMode) {
9469a149f1a0cb39b48b19822c8cf9ef2426cd2251dfMark Lobodzinski        if (!dev_data->extensions.vk_khr_shared_presentable_image) {
947087a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis            if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
9471480a11822ef9a45f577f13644759c0895a49db19Tobin Ehlis                        HandleToUint64(dev_data->device), __LINE__, DRAWSTATE_EXTENSION_NOT_ENABLED, "DS",
94726084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski                        "%s called with presentMode %s which requires the VK_KHR_shared_presentable_image extension, which has not "
94736084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski                        "been enabled.",
94746084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski                        func_name, string_VkPresentModeKHR(pCreateInfo->presentMode)))
94756084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski                return true;
94766084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski        } else if (pCreateInfo->minImageCount != 1) {
94776084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski            if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
9478315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        reinterpret_cast<uint64_t>(dev_data->device), __LINE__, VALIDATION_ERROR_14600ace, "DS",
947987a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis                        "%s called with presentMode %s, but minImageCount value is %d. For shared presentable image, minImageCount "
94806084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski                        "must be 1. %s",
94816084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski                        func_name, string_VkPresentModeKHR(pCreateInfo->presentMode), pCreateInfo->minImageCount,
9482315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_14600ace]))
948387a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis                return true;
948487a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis        }
948587a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis    }
94869e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes
9487d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes    return false;
9488d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes}
9489d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes
9490261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinskistatic void PostCallRecordCreateSwapchainKHR(layer_data *dev_data, VkResult result, const VkSwapchainCreateInfoKHR *pCreateInfo,
9491261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski                                             VkSwapchainKHR *pSwapchain, SURFACE_STATE *surface_state,
9492261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski                                             SWAPCHAIN_NODE *old_swapchain_state) {
94935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == result) {
9494ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes        lock_guard_t lock(global_lock);
9495ddc5201048319558ce66701163a4546ee957af19Chris Forbes        auto swapchain_state = unique_ptr<SWAPCHAIN_NODE>(new SWAPCHAIN_NODE(pCreateInfo, *pSwapchain));
949687a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis        if (VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR == pCreateInfo->presentMode ||
949787a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis            VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR == pCreateInfo->presentMode) {
949887a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis            swapchain_state->shared_presentable = true;
949987a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis        }
9500ddc5201048319558ce66701163a4546ee957af19Chris Forbes        surface_state->swapchain = swapchain_state.get();
950116a1f8f9c4af479b1873e82ff02360817fb658acChris Forbes        dev_data->swapchainMap[*pSwapchain] = std::move(swapchain_state);
9502ddc5201048319558ce66701163a4546ee957af19Chris Forbes    } else {
9503ddc5201048319558ce66701163a4546ee957af19Chris Forbes        surface_state->swapchain = nullptr;
95045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
9505ddc5201048319558ce66701163a4546ee957af19Chris Forbes    // Spec requires that even if CreateSwapchainKHR fails, oldSwapchain behaves as replaced.
95065b5488456e5afa0487f95b805a2aba59b13d69f4Chris Forbes    if (old_swapchain_state) {
95075b5488456e5afa0487f95b805a2aba59b13d69f4Chris Forbes        old_swapchain_state->replaced = true;
95085b5488456e5afa0487f95b805a2aba59b13d69f4Chris Forbes    }
9509ddc5201048319558ce66701163a4546ee957af19Chris Forbes    surface_state->old_swapchain = old_swapchain_state;
9510261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski    return;
9511261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski}
9512261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski
9513261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo,
9514261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski                                                  const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchain) {
951556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
95169a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto surface_state = GetSurfaceState(dev_data->instance_data, pCreateInfo->surface);
95179a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto old_swapchain_state = GetSwapchainNode(dev_data, pCreateInfo->oldSwapchain);
9518261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski
95199ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski    if (PreCallValidateCreateSwapchainKHR(dev_data, "vkCreateSwapChainKHR()", pCreateInfo, surface_state, old_swapchain_state)) {
9520261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski        return VK_ERROR_VALIDATION_FAILED_EXT;
9521261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski    }
9522261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski
9523261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski    VkResult result = dev_data->dispatch_table.CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain);
9524261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski
9525261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski    PostCallRecordCreateSwapchainKHR(dev_data, result, pCreateInfo, pSwapchain, surface_state, old_swapchain_state);
9526ddc5201048319558ce66701163a4546ee957af19Chris Forbes
95275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
95285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
95295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
9530bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks *pAllocator) {
953156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
95323251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
95335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
9534ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
95359a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto swapchain_data = GetSwapchainNode(dev_data, swapchain);
9536b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis    if (swapchain_data) {
9537b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis        if (swapchain_data->images.size() > 0) {
9538b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis            for (auto swapchain_image : swapchain_data->images) {
95395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                auto image_sub = dev_data->imageSubresourceMap.find(swapchain_image);
95405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                if (image_sub != dev_data->imageSubresourceMap.end()) {
95415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    for (auto imgsubpair : image_sub->second) {
95425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        auto image_item = dev_data->imageLayoutMap.find(imgsubpair);
95435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        if (image_item != dev_data->imageLayoutMap.end()) {
95445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                            dev_data->imageLayoutMap.erase(image_item);
95455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                        }
95465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    }
95475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    dev_data->imageSubresourceMap.erase(image_sub);
95485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
95499b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                skip = ClearMemoryObjectBindings(dev_data, HandleToUint64(swapchain_image), kVulkanObjectTypeSwapchainKHR);
955094c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis                dev_data->imageMap.erase(swapchain_image);
95515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
95525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
9553ddc5201048319558ce66701163a4546ee957af19Chris Forbes
95549a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto surface_state = GetSurfaceState(dev_data->instance_data, swapchain_data->createInfo.surface);
9555ddc5201048319558ce66701163a4546ee957af19Chris Forbes        if (surface_state) {
9556cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            if (surface_state->swapchain == swapchain_data) surface_state->swapchain = nullptr;
9557cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            if (surface_state->old_swapchain == swapchain_data) surface_state->old_swapchain = nullptr;
9558ddc5201048319558ce66701163a4546ee957af19Chris Forbes        }
9559ddc5201048319558ce66701163a4546ee957af19Chris Forbes
956016a1f8f9c4af479b1873e82ff02360817fb658acChris Forbes        dev_data->swapchainMap.erase(swapchain);
95615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
9562b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
95633251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (!skip) dev_data->dispatch_table.DestroySwapchainKHR(device, swapchain, pAllocator);
95645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
95655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
9566991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinskistatic bool PreCallValidateGetSwapchainImagesKHR(layer_data *device_data, SWAPCHAIN_NODE *swapchain_state, VkDevice device,
9567991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                                                 uint32_t *pSwapchainImageCount, VkImage *pSwapchainImages) {
9568991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    bool skip = false;
9569991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    if (swapchain_state && pSwapchainImages) {
9570ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes        lock_guard_t lock(global_lock);
9571991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski        // Compare the preliminary value of *pSwapchainImageCount with the value this time:
9572991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski        if (swapchain_state->vkGetSwapchainImagesKHRState == UNCALLED) {
9573991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
9574991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                            HandleToUint64(device), __LINE__, SWAPCHAIN_PRIOR_COUNT, "DS",
9575991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                            "vkGetSwapchainImagesKHR() called with non-NULL pSwapchainImageCount; but no prior positive "
9576991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                            "value has been seen for pSwapchainImages.");
9577991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski        } else if (*pSwapchainImageCount > swapchain_state->get_swapchain_image_count) {
9578991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
9579991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                            HandleToUint64(device), __LINE__, SWAPCHAIN_INVALID_COUNT, "DS",
9580991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                            "vkGetSwapchainImagesKHR() called with non-NULL pSwapchainImageCount, and with "
9581991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                            "pSwapchainImages set to a value (%d) that is greater than the value (%d) that was returned when "
9582991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                            "pSwapchainImageCount was NULL.",
9583991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                            *pSwapchainImageCount, swapchain_state->get_swapchain_image_count);
9584991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski        }
9585991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    }
9586991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    return skip;
9587991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski}
9588991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski
9589991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinskistatic void PostCallRecordGetSwapchainImagesKHR(layer_data *device_data, SWAPCHAIN_NODE *swapchain_state, VkDevice device,
9590991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                                                uint32_t *pSwapchainImageCount, VkImage *pSwapchainImages) {
9591ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    lock_guard_t lock(global_lock);
9592ee52d734440f0770b3ac5ebde5a137d2e40589deChris Forbes
9593991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    if (*pSwapchainImageCount > swapchain_state->images.size()) swapchain_state->images.resize(*pSwapchainImageCount);
9594ee52d734440f0770b3ac5ebde5a137d2e40589deChris Forbes
9595991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    if (pSwapchainImages) {
9596991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski        if (swapchain_state->vkGetSwapchainImagesKHRState < QUERY_DETAILS) {
9597991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            swapchain_state->vkGetSwapchainImagesKHRState = QUERY_DETAILS;
9598991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski        }
9599991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski        for (uint32_t i = 0; i < *pSwapchainImageCount; ++i) {
9600991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            if (swapchain_state->images[i] != VK_NULL_HANDLE) continue;  // Already retrieved this.
9601ee52d734440f0770b3ac5ebde5a137d2e40589deChris Forbes
96025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            IMAGE_LAYOUT_NODE image_layout_node;
96035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            image_layout_node.layout = VK_IMAGE_LAYOUT_UNDEFINED;
9604991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            image_layout_node.format = swapchain_state->createInfo.imageFormat;
96056d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis            // Add imageMap entries for each swapchain image
96066d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis            VkImageCreateInfo image_ci = {};
9607eb6ea7587bdc06e98a89398f113fe3610d270dcbChris Forbes            image_ci.flags = 0;
9608eb6ea7587bdc06e98a89398f113fe3610d270dcbChris Forbes            image_ci.imageType = VK_IMAGE_TYPE_2D;
9609991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            image_ci.format = swapchain_state->createInfo.imageFormat;
9610991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            image_ci.extent.width = swapchain_state->createInfo.imageExtent.width;
9611991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            image_ci.extent.height = swapchain_state->createInfo.imageExtent.height;
9612d1a9776c1a22ec99a3ef0dd44e7f85a78a04d1edTony Barbour            image_ci.extent.depth = 1;
9613eb6ea7587bdc06e98a89398f113fe3610d270dcbChris Forbes            image_ci.mipLevels = 1;
9614991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            image_ci.arrayLayers = swapchain_state->createInfo.imageArrayLayers;
9615eb6ea7587bdc06e98a89398f113fe3610d270dcbChris Forbes            image_ci.samples = VK_SAMPLE_COUNT_1_BIT;
9616eb6ea7587bdc06e98a89398f113fe3610d270dcbChris Forbes            image_ci.tiling = VK_IMAGE_TILING_OPTIMAL;
9617991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            image_ci.usage = swapchain_state->createInfo.imageUsage;
9618991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            image_ci.sharingMode = swapchain_state->createInfo.imageSharingMode;
9619991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            device_data->imageMap[pSwapchainImages[i]] = unique_ptr<IMAGE_STATE>(new IMAGE_STATE(pSwapchainImages[i], &image_ci));
9620991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            auto &image_state = device_data->imageMap[pSwapchainImages[i]];
96211facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis            image_state->valid = false;
9622e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis            image_state->binding.mem = MEMTRACKER_SWAP_CHAIN_IMAGE_KEY;
9623991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            swapchain_state->images[i] = pSwapchainImages[i];
96245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            ImageSubresourcePair subpair = {pSwapchainImages[i], false, VkImageSubresource()};
9625991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            device_data->imageSubresourceMap[pSwapchainImages[i]].push_back(subpair);
9626991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            device_data->imageLayoutMap[subpair] = image_layout_node;
96275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
96285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
9629991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski
9630991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    if (*pSwapchainImageCount) {
9631991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski        if (swapchain_state->vkGetSwapchainImagesKHRState < QUERY_COUNT) {
9632991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            swapchain_state->vkGetSwapchainImagesKHRState = QUERY_COUNT;
9633991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski        }
9634991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski        swapchain_state->get_swapchain_image_count = *pSwapchainImageCount;
9635991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    }
9636991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski}
9637991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski
9638991f2555bc4f571e30b584937c7959805dff67c6Mark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL GetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t *pSwapchainImageCount,
9639991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                                                     VkImage *pSwapchainImages) {
9640991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
9641991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    layer_data *device_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
9642991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski
9643991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    auto swapchain_state = GetSwapchainNode(device_data, swapchain);
9644991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    bool skip = PreCallValidateGetSwapchainImagesKHR(device_data, swapchain_state, device, pSwapchainImageCount, pSwapchainImages);
9645991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski
9646991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    if (!skip) {
9647991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski        result = device_data->dispatch_table.GetSwapchainImagesKHR(device, swapchain, pSwapchainImageCount, pSwapchainImages);
9648991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    }
9649991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski
9650991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    if ((result == VK_SUCCESS || result == VK_INCOMPLETE)) {
9651991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski        PostCallRecordGetSwapchainImagesKHR(device_data, swapchain_state, device, pSwapchainImageCount, pSwapchainImages);
9652991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    }
96535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
96545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
96555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
965689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo) {
965756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map);
96583251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
96595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
9660ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    lock_guard_t lock(global_lock);
96619a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto queue_state = GetQueueState(dev_data, queue);
96621671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes
96636c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes    for (uint32_t i = 0; i < pPresentInfo->waitSemaphoreCount; ++i) {
96649a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto pSemaphore = GetSemaphoreNode(dev_data, pPresentInfo->pWaitSemaphores[i]);
96656c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes        if (pSemaphore && !pSemaphore->signaled) {
96663251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0,
96673251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS",
96683251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "Queue 0x%p is waiting on semaphore 0x%" PRIx64 " that has no way to be signaled.", queue,
96699b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(pPresentInfo->pWaitSemaphores[i]));
96705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
96716c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes    }
9672249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis
96736c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes    for (uint32_t i = 0; i < pPresentInfo->swapchainCount; ++i) {
96749a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis        auto swapchain_data = GetSwapchainNode(dev_data, pPresentInfo->pSwapchains[i]);
9675a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes        if (swapchain_data) {
9676a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes            if (pPresentInfo->pImageIndices[i] >= swapchain_data->images.size()) {
96779b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                skip |=
96789b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                    log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
96799b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            HandleToUint64(pPresentInfo->pSwapchains[i]), __LINE__, DRAWSTATE_SWAPCHAIN_INVALID_IMAGE, "DS",
96809b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            "vkQueuePresentKHR: Swapchain image index too large (%u). There are only %u images in this swapchain.",
96819b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                            pPresentInfo->pImageIndices[i], (uint32_t)swapchain_data->images.size());
9682bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski            } else {
9683a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes                auto image = swapchain_data->images[pPresentInfo->pImageIndices[i]];
96849a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                auto image_state = GetImageState(dev_data, image);
968587a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis
968687a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis                if (image_state->shared_presentable) {
968787a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis                    image_state->layout_locked = true;
968887a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis                }
9689c4f799ed5502f05ce97543e0500b4a19dc5f2461Mark Lobodzinski
96903251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= ValidateImageMemoryIsValid(dev_data, image_state, "vkQueuePresentKHR()");
9691a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes
96921facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis                if (!image_state->acquired) {
96933251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= log_msg(
9694bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                        dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
96959b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        HandleToUint64(pPresentInfo->pSwapchains[i]), __LINE__, DRAWSTATE_SWAPCHAIN_IMAGE_NOT_ACQUIRED, "DS",
9696bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                        "vkQueuePresentKHR: Swapchain image index %u has not been acquired.", pPresentInfo->pImageIndices[i]);
9697a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes                }
9698a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes
9699a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes                vector<VkImageLayout> layouts;
9700a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes                if (FindLayouts(dev_data, image, layouts)) {
9701a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes                    for (auto layout : layouts) {
97026084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski                        if ((layout != VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) &&
9703a149f1a0cb39b48b19822c8cf9ef2426cd2251dfMark Lobodzinski                            (!dev_data->extensions.vk_khr_shared_presentable_image ||
97046084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski                             (layout != VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR))) {
97053251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            skip |=
97062fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen                                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT,
9707315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                        HandleToUint64(queue), __LINE__, VALIDATION_ERROR_11200a20, "DS",
97082fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen                                        "Images passed to present must be in layout "
97096084b78a58b438d27591b81efe30997ac9d88d3cMark Lobodzinski                                        "VK_IMAGE_LAYOUT_PRESENT_SRC_KHR or VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR but is in %s. %s",
9710315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                        string_VkImageLayout(layout), validation_error_map[VALIDATION_ERROR_11200a20]);
9711a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes                        }
97125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                    }
97135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis                }
97145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis            }
97151671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes
97161671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes            // All physical devices and queue families are required to be able
97171671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes            // to present to any native window on Android; require the
97181671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes            // application to have established support on any other platform.
9719d4eaca34eca7f4b4e34190c441a579347bb2016aMark Lobodzinski            if (!dev_data->instance_data->extensions.vk_khr_android_surface) {
97209a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                auto surface_state = GetSurfaceState(dev_data->instance_data, swapchain_data->createInfo.surface);
97211671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes                auto support_it = surface_state->gpu_queue_support.find({dev_data->physical_device, queue_state->queueFamilyIndex});
97221671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes
97231671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes                if (support_it == surface_state->gpu_queue_support.end()) {
97243251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |=
97251671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes                        log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
97269b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                HandleToUint64(pPresentInfo->pSwapchains[i]), __LINE__, DRAWSTATE_SWAPCHAIN_UNSUPPORTED_QUEUE, "DS",
9727cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                                "vkQueuePresentKHR: Presenting image without calling "
9728cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                                "vkGetPhysicalDeviceSurfaceSupportKHR");
97291671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes                } else if (!support_it->second) {
97309b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                    skip |=
97319b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
9732315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                HandleToUint64(pPresentInfo->pSwapchains[i]), __LINE__, VALIDATION_ERROR_31800a18, "DS",
97339b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                "vkQueuePresentKHR: Presenting image on queue that cannot "
97349b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                "present to this surface. %s",
9735315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                validation_error_map[VALIDATION_ERROR_31800a18]);
97361671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes                }
97371671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes            }
97385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis        }
97395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
9740c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis    if (pPresentInfo && pPresentInfo->pNext) {
9741c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis        // Verify ext struct
9742b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf        const auto *present_regions = lvl_find_in_chain<VkPresentRegionsKHR>(pPresentInfo->pNext);
9743b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf        if (present_regions) {
9744b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf            for (uint32_t i = 0; i < present_regions->swapchainCount; ++i) {
9745b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf                auto swapchain_data = GetSwapchainNode(dev_data, pPresentInfo->pSwapchains[i]);
9746b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf                assert(swapchain_data);
9747b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf                VkPresentRegionKHR region = present_regions->pRegions[i];
9748b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf                for (uint32_t j = 0; j < region.rectangleCount; ++j) {
9749b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf                    VkRectLayerKHR rect = region.pRectangles[j];
9750b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf                    // TODO: Need to update these errors to their unique error ids when available
9751b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf                    if ((rect.offset.x + rect.extent.width) > swapchain_data->createInfo.imageExtent.width) {
9752b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf                        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
9753b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf                                        VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, HandleToUint64(pPresentInfo->pSwapchains[i]),
9754b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf                                        __LINE__, DRAWSTATE_SWAPCHAIN_INVALID_IMAGE, "DS",
9755b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf                                        "vkQueuePresentKHR(): For VkPresentRegionKHR down pNext "
9756b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf                                        "chain, pRegion[%i].pRectangles[%i], the sum of offset.x "
9757b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf                                        "(%i) and extent.width (%i) is greater than the "
9758b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf                                        "corresponding swapchain's imageExtent.width (%i).",
9759b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf                                        i, j, rect.offset.x, rect.extent.width, swapchain_data->createInfo.imageExtent.width);
9760b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf                    }
9761b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf                    if ((rect.offset.y + rect.extent.height) > swapchain_data->createInfo.imageExtent.height) {
9762b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf                        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
9763b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf                                        VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, HandleToUint64(pPresentInfo->pSwapchains[i]),
9764b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf                                        __LINE__, DRAWSTATE_SWAPCHAIN_INVALID_IMAGE, "DS",
9765b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf                                        "vkQueuePresentKHR(): For VkPresentRegionKHR down pNext "
9766b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf                                        "chain, pRegion[%i].pRectangles[%i], the sum of offset.y "
9767b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf                                        "(%i) and extent.height (%i) is greater than the "
9768b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf                                        "corresponding swapchain's imageExtent.height (%i).",
9769b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf                                        i, j, rect.offset.y, rect.extent.height, swapchain_data->createInfo.imageExtent.height);
9770b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf                    }
9771b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf                    if (rect.layer > swapchain_data->createInfo.imageArrayLayers) {
9772b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf                        skip |= log_msg(
9773b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf                            dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
9774b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf                            HandleToUint64(pPresentInfo->pSwapchains[i]), __LINE__, DRAWSTATE_SWAPCHAIN_INVALID_IMAGE, "DS",
9775b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf                            "vkQueuePresentKHR(): For VkPresentRegionKHR down pNext chain, pRegion[%i].pRectangles[%i], the "
9776b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf                            "layer (%i) is greater than the corresponding swapchain's imageArrayLayers (%i).",
9777b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf                            i, j, rect.layer, swapchain_data->createInfo.imageArrayLayers);
9778c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis                    }
9779c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis                }
9780b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf            }
9781b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf        }
9782b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf
9783b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf        const auto *present_times_info = lvl_find_in_chain<VkPresentTimesInfoGOOGLE>(pPresentInfo->pNext);
9784b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf        if (present_times_info) {
9785b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf            if (pPresentInfo->swapchainCount != present_times_info->swapchainCount) {
9786b65d7c4e9112072097dde6022999cb6240fc033bJohn Zulauf                skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
97879b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                HandleToUint64(pPresentInfo->pSwapchains[0]), __LINE__,
97885f5e4095d630df9003597a928c86502e3fc83176Tobin Ehlis
9789315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                                VALIDATION_ERROR_118009be, "DS",
97905f5e4095d630df9003597a928c86502e3fc83176Tobin Ehlis                                "vkQueuePresentKHR(): VkPresentTimesInfoGOOGLE.swapchainCount is %i but "
97915f5e4095d630df9003597a928c86502e3fc83176Tobin Ehlis                                "pPresentInfo->swapchainCount is %i. For VkPresentTimesInfoGOOGLE down pNext "
97925f5e4095d630df9003597a928c86502e3fc83176Tobin Ehlis                                "chain of VkPresentInfoKHR, VkPresentTimesInfoGOOGLE.swapchainCount "
97935f5e4095d630df9003597a928c86502e3fc83176Tobin Ehlis                                "must equal VkPresentInfoKHR.swapchainCount.",
97945f5e4095d630df9003597a928c86502e3fc83176Tobin Ehlis                                present_times_info->swapchainCount, pPresentInfo->swapchainCount);
9795c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis            }
9796c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis        }
9797c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis    }
97985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
97993251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (skip) {
98006c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes        return VK_ERROR_VALIDATION_FAILED_EXT;
98016c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes    }
98026c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes
98034a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.QueuePresentKHR(queue, pPresentInfo);
98046c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes
98056c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes    if (result != VK_ERROR_VALIDATION_FAILED_EXT) {
98066c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes        // Semaphore waits occur before error generation, if the call reached
98076c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes        // the ICD. (Confirm?)
98086c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes        for (uint32_t i = 0; i < pPresentInfo->waitSemaphoreCount; ++i) {
98099a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            auto pSemaphore = GetSemaphoreNode(dev_data, pPresentInfo->pWaitSemaphores[i]);
98109867daedbf52debc77d6568162ee21e071699b80Chris Forbes            if (pSemaphore) {
98119867daedbf52debc77d6568162ee21e071699b80Chris Forbes                pSemaphore->signaler.first = VK_NULL_HANDLE;
98126c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes                pSemaphore->signaled = false;
98136c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes            }
98146c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes        }
98159867daedbf52debc77d6568162ee21e071699b80Chris Forbes
9816220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes        for (uint32_t i = 0; i < pPresentInfo->swapchainCount; ++i) {
9817220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes            // Note: this is imperfect, in that we can get confused about what
9818220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes            // did or didn't succeed-- but if the app does that, it's confused
9819220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes            // itself just as much.
9820220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes            auto local_result = pPresentInfo->pResults ? pPresentInfo->pResults[i] : result;
9821220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes
9822cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            if (local_result != VK_SUCCESS && local_result != VK_SUBOPTIMAL_KHR) continue;  // this present didn't actually happen.
9823220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes
9824220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes            // Mark the image as having been released to the WSI
98259a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            auto swapchain_data = GetSwapchainNode(dev_data, pPresentInfo->pSwapchains[i]);
9826220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes            auto image = swapchain_data->images[pPresentInfo->pImageIndices[i]];
98279a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            auto image_state = GetImageState(dev_data, image);
98281facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis            image_state->acquired = false;
9829220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes        }
9830220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes
98319867daedbf52debc77d6568162ee21e071699b80Chris Forbes        // Note: even though presentation is directed to a queue, there is no
98329867daedbf52debc77d6568162ee21e071699b80Chris Forbes        // direct ordering between QP and subsequent work, so QP (and its
98339867daedbf52debc77d6568162ee21e071699b80Chris Forbes        // semaphore waits) /never/ participate in any completion proof.
98346c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes    }
98351344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis
98365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
98375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
98385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
9839c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinskistatic bool PreCallValidateCreateSharedSwapchainsKHR(layer_data *dev_data, uint32_t swapchainCount,
9840c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski                                                     const VkSwapchainCreateInfoKHR *pCreateInfos, VkSwapchainKHR *pSwapchains,
9841c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski                                                     std::vector<SURFACE_STATE *> &surface_state,
9842c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski                                                     std::vector<SWAPCHAIN_NODE *> &old_swapchain_state) {
98430342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski    if (pCreateInfos) {
9844ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes        lock_guard_t lock(global_lock);
98450342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski        for (uint32_t i = 0; i < swapchainCount; i++) {
98469a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            surface_state.push_back(GetSurfaceState(dev_data->instance_data, pCreateInfos[i].surface));
98479a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis            old_swapchain_state.push_back(GetSwapchainNode(dev_data, pCreateInfos[i].oldSwapchain));
98489ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski            std::stringstream func_name;
98499ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski            func_name << "vkCreateSharedSwapchainsKHR[" << swapchainCount << "]";
9850bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski            if (PreCallValidateCreateSwapchainKHR(dev_data, func_name.str().c_str(), &pCreateInfos[i], surface_state[i],
9851bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                  old_swapchain_state[i])) {
9852c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski                return true;
98530342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski            }
98540342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski        }
98550342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski    }
9856c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski    return false;
9857c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski}
98580342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski
9859c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinskistatic void PostCallRecordCreateSharedSwapchainsKHR(layer_data *dev_data, VkResult result, uint32_t swapchainCount,
9860c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski                                                    const VkSwapchainCreateInfoKHR *pCreateInfos, VkSwapchainKHR *pSwapchains,
9861c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski                                                    std::vector<SURFACE_STATE *> &surface_state,
9862c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski                                                    std::vector<SWAPCHAIN_NODE *> &old_swapchain_state) {
98630342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski    if (VK_SUCCESS == result) {
98640342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski        for (uint32_t i = 0; i < swapchainCount; i++) {
98650342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski            auto swapchain_state = unique_ptr<SWAPCHAIN_NODE>(new SWAPCHAIN_NODE(&pCreateInfos[i], pSwapchains[i]));
986687a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis            if (VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR == pCreateInfos[i].presentMode ||
986787a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis                VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR == pCreateInfos[i].presentMode) {
986887a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis                swapchain_state->shared_presentable = true;
986987a57d8e822316de46ee97f514187331b1f4f09dTobin Ehlis            }
98700342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski            surface_state[i]->swapchain = swapchain_state.get();
987116a1f8f9c4af479b1873e82ff02360817fb658acChris Forbes            dev_data->swapchainMap[pSwapchains[i]] = std::move(swapchain_state);
98720342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski        }
98730342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski    } else {
98740342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski        for (uint32_t i = 0; i < swapchainCount; i++) {
98750342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski            surface_state[i]->swapchain = nullptr;
98760342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski        }
98770342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski    }
98780342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski    // Spec requires that even if CreateSharedSwapchainKHR fails, oldSwapchain behaves as replaced.
98790342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski    for (uint32_t i = 0; i < swapchainCount; i++) {
98800342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski        if (old_swapchain_state[i]) {
98810342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski            old_swapchain_state[i]->replaced = true;
98820342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski        }
98830342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski        surface_state[i]->old_swapchain = old_swapchain_state[i];
98840342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski    }
9885c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski    return;
9886c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski}
9887c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski
9888c6cd632d064579a64e61d8704b411d0e4ace7adaMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateSharedSwapchainsKHR(VkDevice device, uint32_t swapchainCount,
9889c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski                                                         const VkSwapchainCreateInfoKHR *pCreateInfos,
9890c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski                                                         const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchains) {
989156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
9892c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski    std::vector<SURFACE_STATE *> surface_state;
9893c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski    std::vector<SWAPCHAIN_NODE *> old_swapchain_state;
9894c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski
9895c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski    if (PreCallValidateCreateSharedSwapchainsKHR(dev_data, swapchainCount, pCreateInfos, pSwapchains, surface_state,
9896c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski                                                 old_swapchain_state)) {
9897c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski        return VK_ERROR_VALIDATION_FAILED_EXT;
9898c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski    }
9899c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski
9900c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski    VkResult result =
9901c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski        dev_data->dispatch_table.CreateSharedSwapchainsKHR(device, swapchainCount, pCreateInfos, pAllocator, pSwapchains);
9902c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski
9903c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski    PostCallRecordCreateSharedSwapchainsKHR(dev_data, result, swapchainCount, pCreateInfos, pSwapchains, surface_state,
9904c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski                                            old_swapchain_state);
99050342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski
9906c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young    return result;
9907c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young}
9908c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young
9909ca0956fd78425c5ce5f29a017d10807e6a24d331Mike Schuchardtstatic bool PreCallValidateAcquireNextImageKHR(layer_data *dev_data, VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout,
9910ca0956fd78425c5ce5f29a017d10807e6a24d331Mike Schuchardt                                               VkSemaphore semaphore, VkFence fence, uint32_t *pImageIndex) {
99113251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
9912449670637ef4214b33018f497cf10daeff9dc85bChris Forbes    if (fence == VK_NULL_HANDLE && semaphore == VK_NULL_HANDLE) {
99133251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
99149b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        HandleToUint64(device), __LINE__, DRAWSTATE_SWAPCHAIN_NO_SYNC_FOR_ACQUIRE, "DS",
99153251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "vkAcquireNextImageKHR: Semaphore and fence cannot both be VK_NULL_HANDLE. There would be no way "
99163251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "to determine the completion of this operation.");
9917449670637ef4214b33018f497cf10daeff9dc85bChris Forbes    }
9918449670637ef4214b33018f497cf10daeff9dc85bChris Forbes
99199a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto pSemaphore = GetSemaphoreNode(dev_data, semaphore);
992006d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt    if (pSemaphore && pSemaphore->scope == kSyncScopeInternal && pSemaphore->signaled) {
99213251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT,
9922315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        HandleToUint64(semaphore), __LINE__, VALIDATION_ERROR_16400a0c, "DS",
99233251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "vkAcquireNextImageKHR: Semaphore must not be currently signaled or in a wait state. %s",
9924315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis                        validation_error_map[VALIDATION_ERROR_16400a0c]);
99255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
9926f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes
99279a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto pFence = GetFenceNode(dev_data, fence);
9928f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes    if (pFence) {
99293251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= ValidateFenceForSubmit(dev_data, pFence);
99305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
99314a5614452104c88cb04390dac882dd94ebdcc3deChris Forbes
99329a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto swapchain_data = GetSwapchainNode(dev_data, swapchain);
9933fc9f0448c3cb6ba4fc018fefe761bb43a1884846Chris Forbes    if (swapchain_data->replaced) {
99343251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
99359b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        HandleToUint64(swapchain), __LINE__, DRAWSTATE_SWAPCHAIN_REPLACED, "DS",
99363251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "vkAcquireNextImageKHR: This swapchain has been replaced. The application can still "
99373251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "present any images it has acquired, but cannot acquire any more.");
9938fc9f0448c3cb6ba4fc018fefe761bb43a1884846Chris Forbes    }
9939fc9f0448c3cb6ba4fc018fefe761bb43a1884846Chris Forbes
99409a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto physical_device_state = GetPhysicalDeviceState(dev_data->instance_data, dev_data->physical_device);
99414a5614452104c88cb04390dac882dd94ebdcc3deChris Forbes    if (physical_device_state->vkGetPhysicalDeviceSurfaceCapabilitiesKHRState != UNCALLED) {
99426569ab421f45f905e69fa7345bda4fe5b87e9045Mark Lobodzinski        uint64_t acquired_images = std::count_if(swapchain_data->images.begin(), swapchain_data->images.end(),
99439a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis                                                 [=](VkImage image) { return GetImageState(dev_data, image)->acquired; });
99444a5614452104c88cb04390dac882dd94ebdcc3deChris Forbes        if (acquired_images > swapchain_data->images.size() - physical_device_state->surfaceCapabilities.minImageCount) {
99453251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |=
99466569ab421f45f905e69fa7345bda4fe5b87e9045Mark Lobodzinski                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
99479b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        HandleToUint64(swapchain), __LINE__, DRAWSTATE_SWAPCHAIN_TOO_MANY_IMAGES, "DS",
99486569ab421f45f905e69fa7345bda4fe5b87e9045Mark Lobodzinski                        "vkAcquireNextImageKHR: Application has already acquired the maximum number of images (0x%" PRIxLEAST64 ")",
99496569ab421f45f905e69fa7345bda4fe5b87e9045Mark Lobodzinski                        acquired_images);
99504a5614452104c88cb04390dac882dd94ebdcc3deChris Forbes        }
99514a5614452104c88cb04390dac882dd94ebdcc3deChris Forbes    }
995275269fc9e5cc9696ddf3dd28ff201c9b2526dc7aThomas Louis
995375269fc9e5cc9696ddf3dd28ff201c9b2526dc7aThomas Louis    if (swapchain_data->images.size() == 0) {
99543251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
99559b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        HandleToUint64(swapchain), __LINE__, DRAWSTATE_SWAPCHAIN_IMAGES_NOT_FOUND, "DS",
99563251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "vkAcquireNextImageKHR: No images found to acquire from. Application probably did not call "
99573251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                        "vkGetSwapchainImagesKHR after swapchain creation.");
995875269fc9e5cc9696ddf3dd28ff201c9b2526dc7aThomas Louis    }
9959ca0956fd78425c5ce5f29a017d10807e6a24d331Mike Schuchardt    return skip;
9960ca0956fd78425c5ce5f29a017d10807e6a24d331Mike Schuchardt}
9961ca0956fd78425c5ce5f29a017d10807e6a24d331Mike Schuchardt
9962ca0956fd78425c5ce5f29a017d10807e6a24d331Mike Schuchardtstatic void PostCallRecordAcquireNextImageKHR(layer_data *dev_data, VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout,
9963ca0956fd78425c5ce5f29a017d10807e6a24d331Mike Schuchardt                                              VkSemaphore semaphore, VkFence fence, uint32_t *pImageIndex) {
9964ca0956fd78425c5ce5f29a017d10807e6a24d331Mike Schuchardt    auto pFence = GetFenceNode(dev_data, fence);
9965980fe4b66c791e16eadda9b51f833eb626c5572fMike Schuchardt    if (pFence && pFence->scope == kSyncScopeInternal) {
9966980fe4b66c791e16eadda9b51f833eb626c5572fMike Schuchardt        // Treat as inflight since it is valid to wait on this fence, even in cases where it is technically a temporary
9967980fe4b66c791e16eadda9b51f833eb626c5572fMike Schuchardt        // import
9968980fe4b66c791e16eadda9b51f833eb626c5572fMike Schuchardt        pFence->state = FENCE_INFLIGHT;
9969980fe4b66c791e16eadda9b51f833eb626c5572fMike Schuchardt        pFence->signaler.first = VK_NULL_HANDLE;  // ANI isn't on a queue, so this can't participate in a completion proof.
9970ca0956fd78425c5ce5f29a017d10807e6a24d331Mike Schuchardt    }
9971ca0956fd78425c5ce5f29a017d10807e6a24d331Mike Schuchardt
9972ca0956fd78425c5ce5f29a017d10807e6a24d331Mike Schuchardt    auto pSemaphore = GetSemaphoreNode(dev_data, semaphore);
9973980fe4b66c791e16eadda9b51f833eb626c5572fMike Schuchardt    if (pSemaphore && pSemaphore->scope == kSyncScopeInternal) {
9974980fe4b66c791e16eadda9b51f833eb626c5572fMike Schuchardt        // Treat as signaled since it is valid to wait on this semaphore, even in cases where it is technically a
9975980fe4b66c791e16eadda9b51f833eb626c5572fMike Schuchardt        // temporary import
9976980fe4b66c791e16eadda9b51f833eb626c5572fMike Schuchardt        pSemaphore->signaled = true;
9977980fe4b66c791e16eadda9b51f833eb626c5572fMike Schuchardt        pSemaphore->signaler.first = VK_NULL_HANDLE;
9978ca0956fd78425c5ce5f29a017d10807e6a24d331Mike Schuchardt    }
9979ca0956fd78425c5ce5f29a017d10807e6a24d331Mike Schuchardt
9980ca0956fd78425c5ce5f29a017d10807e6a24d331Mike Schuchardt    // Mark the image as acquired.
9981ca0956fd78425c5ce5f29a017d10807e6a24d331Mike Schuchardt    auto swapchain_data = GetSwapchainNode(dev_data, swapchain);
9982ca0956fd78425c5ce5f29a017d10807e6a24d331Mike Schuchardt    auto image = swapchain_data->images[*pImageIndex];
9983ca0956fd78425c5ce5f29a017d10807e6a24d331Mike Schuchardt    auto image_state = GetImageState(dev_data, image);
9984ca0956fd78425c5ce5f29a017d10807e6a24d331Mike Schuchardt    image_state->acquired = true;
9985ca0956fd78425c5ce5f29a017d10807e6a24d331Mike Schuchardt    image_state->shared_presentable = swapchain_data->shared_presentable;
9986ca0956fd78425c5ce5f29a017d10807e6a24d331Mike Schuchardt}
998775269fc9e5cc9696ddf3dd28ff201c9b2526dc7aThomas Louis
9988ca0956fd78425c5ce5f29a017d10807e6a24d331Mike SchuchardtVKAPI_ATTR VkResult VKAPI_CALL AcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout,
9989ca0956fd78425c5ce5f29a017d10807e6a24d331Mike Schuchardt                                                   VkSemaphore semaphore, VkFence fence, uint32_t *pImageIndex) {
9990ca0956fd78425c5ce5f29a017d10807e6a24d331Mike Schuchardt    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
9991ca0956fd78425c5ce5f29a017d10807e6a24d331Mike Schuchardt
9992ca0956fd78425c5ce5f29a017d10807e6a24d331Mike Schuchardt    unique_lock_t lock(global_lock);
9993ca0956fd78425c5ce5f29a017d10807e6a24d331Mike Schuchardt    bool skip = PreCallValidateAcquireNextImageKHR(dev_data, device, swapchain, timeout, semaphore, fence, pImageIndex);
9994b9e992386a44404152747d66817a733aa127e281Jeremy Hayes    lock.unlock();
99951344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis
99963251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
9997f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes
99984a0754042cf090e131e9e769d8a3633c228625beChris Forbes    VkResult result = dev_data->dispatch_table.AcquireNextImageKHR(device, swapchain, timeout, semaphore, fence, pImageIndex);
9999f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes
10000f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes    lock.lock();
10001f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes    if (result == VK_SUCCESS || result == VK_SUBOPTIMAL_KHR) {
10002ca0956fd78425c5ce5f29a017d10807e6a24d331Mike Schuchardt        PostCallRecordAcquireNextImageKHR(dev_data, device, swapchain, timeout, semaphore, fence, pImageIndex);
100035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
10004f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes    lock.unlock();
100051344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis
100065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return result;
100075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
100085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
10009f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL EnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount,
10010f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski                                                        VkPhysicalDevice *pPhysicalDevices) {
100113251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
1001256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map);
10013bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis    assert(instance_data);
10014219f00ffed576643641976122fa1db8e5fce5dc1Chris Forbes
10015bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis    // For this instance, flag when vkEnumeratePhysicalDevices goes to QUERY_COUNT and then QUERY_DETAILS
10016bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis    if (NULL == pPhysicalDevices) {
10017bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis        instance_data->vkEnumeratePhysicalDevicesState = QUERY_COUNT;
10018f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski    } else {
10019bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis        if (UNCALLED == instance_data->vkEnumeratePhysicalDevicesState) {
10020bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis            // Flag warning here. You can call this without having queried the count, but it may not be
10021bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis            // robust on platforms with multiple physical devices.
100223251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
100233251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            0, __LINE__, DEVLIMITS_MISSING_QUERY_COUNT, "DL",
100243251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "Call sequence has vkEnumeratePhysicalDevices() w/ non-NULL pPhysicalDevices. You should first "
100253251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "call vkEnumeratePhysicalDevices() w/ NULL pPhysicalDevices to query pPhysicalDeviceCount.");
10026cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        }  // TODO : Could also flag a warning if re-calling this function in QUERY_DETAILS state
10027bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis        else if (instance_data->physical_devices_count != *pPhysicalDeviceCount) {
10028bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis            // Having actual count match count from app is not a requirement, so this can be a warning
100293251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski            skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT,
100303251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_COUNT_MISMATCH, "DL",
100313251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "Call to vkEnumeratePhysicalDevices() w/ pPhysicalDeviceCount value %u, but actual count "
100323251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "supported by this instance is %u.",
100333251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            *pPhysicalDeviceCount, instance_data->physical_devices_count);
10034bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis        }
10035bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis        instance_data->vkEnumeratePhysicalDevicesState = QUERY_DETAILS;
10036f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski    }
100373251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (skip) {
10038bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis        return VK_ERROR_VALIDATION_FAILED_EXT;
10039bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis    }
10040bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis    VkResult result = instance_data->dispatch_table.EnumeratePhysicalDevices(instance, pPhysicalDeviceCount, pPhysicalDevices);
10041bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis    if (NULL == pPhysicalDevices) {
10042bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis        instance_data->physical_devices_count = *pPhysicalDeviceCount;
10043cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    } else if (result == VK_SUCCESS) {  // Save physical devices
10044bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis        for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++) {
10045bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis            auto &phys_device_state = instance_data->physical_device_map[pPhysicalDevices[i]];
10046bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis            phys_device_state.phys_device = pPhysicalDevices[i];
10047bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis            // Init actual features for each physical device
10048bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis            instance_data->dispatch_table.GetPhysicalDeviceFeatures(pPhysicalDevices[i], &phys_device_state.features);
10049bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis        }
10050bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis    }
10051bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis    return result;
10052f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski}
10053f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski
1005443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis// Common function to handle validation for GetPhysicalDeviceQueueFamilyProperties & 2KHR version
1005543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic bool ValidateCommonGetPhysicalDeviceQueueFamilyProperties(instance_layer_data *instance_data,
1005643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis                                                                 PHYSICAL_DEVICE_STATE *pd_state,
100575770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                                                                 uint32_t requested_queue_family_property_count, bool qfp_null,
100585770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                                                                 const char *caller_name) {
1005943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis    bool skip = false;
100605770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    if (!qfp_null) {
100615770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus        // Verify that for each physical device, this command is called first with NULL pQueueFamilyProperties in order to get count
1006243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis        if (UNCALLED == pd_state->vkGetPhysicalDeviceQueueFamilyPropertiesState) {
100635770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus            skip |= log_msg(
100645770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
100659b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                HandleToUint64(pd_state->phys_device), __LINE__, DEVLIMITS_MISSING_QUERY_COUNT, "DL",
100665770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                "%s is called with non-NULL pQueueFamilyProperties before obtaining pQueueFamilyPropertyCount. It is recommended "
100675770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                "to first call %s with NULL pQueueFamilyProperties in order to obtain the maximal pQueueFamilyPropertyCount.",
100685770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                caller_name, caller_name);
100695770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus            // Then verify that pCount that is passed in on second call matches what was returned
100705770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus        } else if (pd_state->queue_family_count != requested_queue_family_property_count) {
100715770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus            skip |= log_msg(
100725770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
100739b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                HandleToUint64(pd_state->phys_device), __LINE__, DEVLIMITS_COUNT_MISMATCH, "DL",
100745770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                "%s is called with non-NULL pQueueFamilyProperties and pQueueFamilyPropertyCount value %" PRIu32
100755770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                ", but the largest previously returned pQueueFamilyPropertyCount for this physicalDevice is %" PRIu32
100765770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                ". It is recommended to instead receive all the properties by calling %s with pQueueFamilyPropertyCount that was "
100775770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                "previously obtained by calling %s with NULL pQueueFamilyProperties.",
100785770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                caller_name, requested_queue_family_property_count, pd_state->queue_family_count, caller_name, caller_name);
1007943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis        }
1008043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis        pd_state->vkGetPhysicalDeviceQueueFamilyPropertiesState = QUERY_DETAILS;
1008143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis    }
100825770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
1008343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis    return skip;
1008443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis}
1008543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis
1008643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic bool PreCallValidateGetPhysicalDeviceQueueFamilyProperties(instance_layer_data *instance_data,
100875770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                                                                  PHYSICAL_DEVICE_STATE *pd_state,
100885770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                                                                  uint32_t *pQueueFamilyPropertyCount,
1008943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis                                                                  VkQueueFamilyProperties *pQueueFamilyProperties) {
100905770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    return ValidateCommonGetPhysicalDeviceQueueFamilyProperties(instance_data, pd_state, *pQueueFamilyPropertyCount,
100915770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                                                                (nullptr == pQueueFamilyProperties),
1009243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis                                                                "vkGetPhysicalDeviceQueueFamilyProperties()");
1009343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis}
1009443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis
1009543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic bool PreCallValidateGetPhysicalDeviceQueueFamilyProperties2KHR(instance_layer_data *instance_data,
1009643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis                                                                      PHYSICAL_DEVICE_STATE *pd_state,
1009743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis                                                                      uint32_t *pQueueFamilyPropertyCount,
1009843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis                                                                      VkQueueFamilyProperties2KHR *pQueueFamilyProperties) {
100995770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    return ValidateCommonGetPhysicalDeviceQueueFamilyProperties(instance_data, pd_state, *pQueueFamilyPropertyCount,
101005770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                                                                (nullptr == pQueueFamilyProperties),
1010143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis                                                                "vkGetPhysicalDeviceQueueFamilyProperties2KHR()");
1010243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis}
1010343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis
1010443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis// Common function to update state for GetPhysicalDeviceQueueFamilyProperties & 2KHR version
1010543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic void StateUpdateCommonGetPhysicalDeviceQueueFamilyProperties(PHYSICAL_DEVICE_STATE *pd_state, uint32_t count,
1010643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis                                                                    VkQueueFamilyProperties2KHR *pQueueFamilyProperties) {
1010743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis    if (!pQueueFamilyProperties) {
101085770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus        if (UNCALLED == pd_state->vkGetPhysicalDeviceQueueFamilyPropertiesState)
101095770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus            pd_state->vkGetPhysicalDeviceQueueFamilyPropertiesState = QUERY_COUNT;
101105770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus        pd_state->queue_family_count = count;
1011143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis    } else {  // Save queue family properties
101125770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus        pd_state->vkGetPhysicalDeviceQueueFamilyPropertiesState = QUERY_DETAILS;
101135770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus        pd_state->queue_family_count = std::max(pd_state->queue_family_count, count);
101145770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
101155770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus        pd_state->queue_family_properties.resize(std::max(static_cast<uint32_t>(pd_state->queue_family_properties.size()), count));
101165770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus        for (uint32_t i = 0; i < count; ++i) {
1011743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis            pd_state->queue_family_properties[i] = pQueueFamilyProperties[i].queueFamilyProperties;
1011843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis        }
1011943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis    }
1012043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis}
1012143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis
1012243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic void PostCallRecordGetPhysicalDeviceQueueFamilyProperties(PHYSICAL_DEVICE_STATE *pd_state, uint32_t count,
1012343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis                                                                 VkQueueFamilyProperties *pQueueFamilyProperties) {
1012443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis    VkQueueFamilyProperties2KHR *pqfp = nullptr;
1012543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis    std::vector<VkQueueFamilyProperties2KHR> qfp;
1012643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis    qfp.resize(count);
1012743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis    if (pQueueFamilyProperties) {
1012843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis        for (uint32_t i = 0; i < count; ++i) {
1012943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis            qfp[i].sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2_KHR;
1013043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis            qfp[i].pNext = nullptr;
1013143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis            qfp[i].queueFamilyProperties = pQueueFamilyProperties[i];
1013243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis        }
1013343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis        pqfp = qfp.data();
1013443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis    }
1013543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis    StateUpdateCommonGetPhysicalDeviceQueueFamilyProperties(pd_state, count, pqfp);
1013643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis}
1013743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis
1013843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic void PostCallRecordGetPhysicalDeviceQueueFamilyProperties2KHR(PHYSICAL_DEVICE_STATE *pd_state, uint32_t count,
1013943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis                                                                     VkQueueFamilyProperties2KHR *pQueueFamilyProperties) {
1014043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis    StateUpdateCommonGetPhysicalDeviceQueueFamilyProperties(pd_state, count, pQueueFamilyProperties);
1014143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis}
1014243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis
101435770f8ad21c40b2475201e73e9368a899b6886d0Petr KrausVKAPI_ATTR void VKAPI_CALL GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice,
101445770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                                                                  uint32_t *pQueueFamilyPropertyCount,
10145bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                                  VkQueueFamilyProperties *pQueueFamilyProperties) {
1014656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map);
101479a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto physical_device_state = GetPhysicalDeviceState(instance_data, physicalDevice);
1014843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis    assert(physical_device_state);
10149ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
101505770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
101515770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    bool skip = PreCallValidateGetPhysicalDeviceQueueFamilyProperties(instance_data, physical_device_state,
101525770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                                                                      pQueueFamilyPropertyCount, pQueueFamilyProperties);
101535770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
101545770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    lock.unlock();
101555770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
101565770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    if (skip) return;
101575770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
101585770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    instance_data->dispatch_table.GetPhysicalDeviceQueueFamilyProperties(physicalDevice, pQueueFamilyPropertyCount,
101595770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus                                                                         pQueueFamilyProperties);
101605770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
101615770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    lock.lock();
101625770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    PostCallRecordGetPhysicalDeviceQueueFamilyProperties(physical_device_state, *pQueueFamilyPropertyCount, pQueueFamilyProperties);
1016343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis}
1016443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis
1016543947a6175e3e942e04d902f4d18928168e2d0dbTobin EhlisVKAPI_ATTR void VKAPI_CALL GetPhysicalDeviceQueueFamilyProperties2KHR(VkPhysicalDevice physicalDevice,
1016643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis                                                                      uint32_t *pQueueFamilyPropertyCount,
1016743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis                                                                      VkQueueFamilyProperties2KHR *pQueueFamilyProperties) {
1016856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map);
101699a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto physical_device_state = GetPhysicalDeviceState(instance_data, physicalDevice);
1017043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis    assert(physical_device_state);
10171ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
101725770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
1017343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis    bool skip = PreCallValidateGetPhysicalDeviceQueueFamilyProperties2KHR(instance_data, physical_device_state,
1017443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis                                                                          pQueueFamilyPropertyCount, pQueueFamilyProperties);
101755770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
101765770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    lock.unlock();
101775770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
101785770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    if (skip) return;
101795770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
1018043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis    instance_data->dispatch_table.GetPhysicalDeviceQueueFamilyProperties2KHR(physicalDevice, pQueueFamilyPropertyCount,
1018143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis                                                                             pQueueFamilyProperties);
101825770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus
101835770f8ad21c40b2475201e73e9368a899b6886d0Petr Kraus    lock.lock();
1018443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis    PostCallRecordGetPhysicalDeviceQueueFamilyProperties2KHR(physical_device_state, *pQueueFamilyPropertyCount,
1018543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis                                                             pQueueFamilyProperties);
10186cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski}
10187cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski
10188bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskitemplate <typename TCreateInfo, typename FPtr>
10189bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic VkResult CreateSurface(VkInstance instance, TCreateInfo const *pCreateInfo, VkAllocationCallbacks const *pAllocator,
10190bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                              VkSurfaceKHR *pSurface, FPtr fptr) {
1019156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map);
10192747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
10193747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    // Call down the call chain:
10194747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    VkResult result = (instance_data->dispatch_table.*fptr)(instance, pCreateInfo, pAllocator, pSurface);
10195747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
10196747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    if (result == VK_SUCCESS) {
10197ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes        unique_lock_t lock(global_lock);
10198747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes        instance_data->surface_map[*pSurface] = SURFACE_STATE(*pSurface);
10199747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes        lock.unlock();
10200747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    }
10201747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
10202747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    return result;
10203747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes}
10204747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
10205747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR void VKAPI_CALL DestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks *pAllocator) {
102063251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
1020756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map);
10208ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
102099a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto surface_state = GetSurfaceState(instance_data, surface);
10210747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
10211991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    if ((surface_state) && (surface_state->swapchain)) {
10212991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski        skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
10213991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            HandleToUint64(instance), __LINE__, VALIDATION_ERROR_26c009e4, "DS",
10214991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            "vkDestroySurfaceKHR() called before its associated VkSwapchainKHR was destroyed. %s",
10215991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            validation_error_map[VALIDATION_ERROR_26c009e4]);
10216747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    }
10217991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    instance_data->surface_map.erase(surface);
10218747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    lock.unlock();
102193251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (!skip) {
10220747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes        instance_data->dispatch_table.DestroySurfaceKHR(instance, surface, pAllocator);
10221747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    }
10222747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes}
10223747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
102246f2ed666809272002a31b3b4f8adf6581cb41819Norbert NopperVKAPI_ATTR VkResult VKAPI_CALL CreateDisplayPlaneSurfaceKHR(VkInstance instance, const VkDisplaySurfaceCreateInfoKHR *pCreateInfo,
102256f2ed666809272002a31b3b4f8adf6581cb41819Norbert Nopper                                                            const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
102266f2ed666809272002a31b3b4f8adf6581cb41819Norbert Nopper    return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateDisplayPlaneSurfaceKHR);
102276f2ed666809272002a31b3b4f8adf6581cb41819Norbert Nopper}
102286f2ed666809272002a31b3b4f8adf6581cb41819Norbert Nopper
10229747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_ANDROID_KHR
10230747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR *pCreateInfo,
10231747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes                                                       const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
10232747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateAndroidSurfaceKHR);
10233747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes}
10234cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif  // VK_USE_PLATFORM_ANDROID_KHR
10235747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
10236747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_MIR_KHR
10237747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateMirSurfaceKHR(VkInstance instance, const VkMirSurfaceCreateInfoKHR *pCreateInfo,
10238747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes                                                   const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
10239747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateMirSurfaceKHR);
10240747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes}
10241f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
10242f25d461667ca2db55147d2be49f179945edf24dbPetr KrausVKAPI_ATTR VkBool32 VKAPI_CALL GetPhysicalDeviceMirPresentationSupportKHR(VkPhysicalDevice physicalDevice,
10243f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus                                                                          uint32_t queueFamilyIndex, MirConnection *connection) {
10244f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    bool skip = false;
10245f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map);
10246f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
10247ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
10248f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    const auto pd_state = GetPhysicalDeviceState(instance_data, physicalDevice);
10249f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
10250315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis    skip |= ValidatePhysicalDeviceQueueFamily(instance_data, pd_state, queueFamilyIndex, VALIDATION_ERROR_2d2009e2,
10251f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus                                              "vkGetPhysicalDeviceMirPresentationSupportKHR", "queueFamilyIndex");
10252f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
10253f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    lock.unlock();
10254f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
10255f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    if (skip) return VK_FALSE;
10256f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
10257f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    // Call down the call chain:
10258f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    VkBool32 result =
10259f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus        instance_data->dispatch_table.GetPhysicalDeviceMirPresentationSupportKHR(physicalDevice, queueFamilyIndex, connection);
10260f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
10261f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    return result;
10262f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus}
10263cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif  // VK_USE_PLATFORM_MIR_KHR
10264747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
10265747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_WAYLAND_KHR
10266747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateWaylandSurfaceKHR(VkInstance instance, const VkWaylandSurfaceCreateInfoKHR *pCreateInfo,
10267747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes                                                       const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
10268a9c6cc532ce0ef61d48d1419a96aae51b0e4c64aTobin Ehlis    return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateWaylandSurfaceKHR);
10269747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes}
10270f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
10271f25d461667ca2db55147d2be49f179945edf24dbPetr KrausVKAPI_ATTR VkBool32 VKAPI_CALL GetPhysicalDeviceWaylandPresentationSupportKHR(VkPhysicalDevice physicalDevice,
10272f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus                                                                              uint32_t queueFamilyIndex,
10273f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus                                                                              struct wl_display *display) {
10274f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    bool skip = false;
10275f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map);
10276f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
10277ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
10278f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    const auto pd_state = GetPhysicalDeviceState(instance_data, physicalDevice);
10279f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
10280315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis    skip |= ValidatePhysicalDeviceQueueFamily(instance_data, pd_state, queueFamilyIndex, VALIDATION_ERROR_2f000a34,
10281f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus                                              "vkGetPhysicalDeviceWaylandPresentationSupportKHR", "queueFamilyIndex");
10282f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
10283f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    lock.unlock();
10284f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
10285f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    if (skip) return VK_FALSE;
10286f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
10287f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    // Call down the call chain:
10288f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    VkBool32 result =
10289f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus        instance_data->dispatch_table.GetPhysicalDeviceWaylandPresentationSupportKHR(physicalDevice, queueFamilyIndex, display);
10290f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
10291f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    return result;
10292f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus}
10293cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif  // VK_USE_PLATFORM_WAYLAND_KHR
10294747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
10295747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_WIN32_KHR
10296747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateWin32SurfaceKHR(VkInstance instance, const VkWin32SurfaceCreateInfoKHR *pCreateInfo,
10297747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes                                                     const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
10298747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateWin32SurfaceKHR);
10299747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes}
10300f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
10301f25d461667ca2db55147d2be49f179945edf24dbPetr KrausVKAPI_ATTR VkBool32 VKAPI_CALL GetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice physicalDevice,
10302f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus                                                                            uint32_t queueFamilyIndex) {
10303f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    bool skip = false;
10304f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map);
10305f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
10306ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
10307f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    const auto pd_state = GetPhysicalDeviceState(instance_data, physicalDevice);
10308f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
10309315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis    skip |= ValidatePhysicalDeviceQueueFamily(instance_data, pd_state, queueFamilyIndex, VALIDATION_ERROR_2f200a3a,
10310f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus                                              "vkGetPhysicalDeviceWin32PresentationSupportKHR", "queueFamilyIndex");
10311f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
10312f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    lock.unlock();
10313f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
10314f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    if (skip) return VK_FALSE;
10315f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
10316f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    // Call down the call chain:
10317f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    VkBool32 result = instance_data->dispatch_table.GetPhysicalDeviceWin32PresentationSupportKHR(physicalDevice, queueFamilyIndex);
10318f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
10319f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    return result;
10320f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus}
10321cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif  // VK_USE_PLATFORM_WIN32_KHR
10322747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
10323747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_XCB_KHR
10324747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateXcbSurfaceKHR(VkInstance instance, const VkXcbSurfaceCreateInfoKHR *pCreateInfo,
10325747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes                                                   const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
10326747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateXcbSurfaceKHR);
10327747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes}
10328f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
10329f25d461667ca2db55147d2be49f179945edf24dbPetr KrausVKAPI_ATTR VkBool32 VKAPI_CALL GetPhysicalDeviceXcbPresentationSupportKHR(VkPhysicalDevice physicalDevice,
10330f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus                                                                          uint32_t queueFamilyIndex, xcb_connection_t *connection,
10331f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus                                                                          xcb_visualid_t visual_id) {
10332f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    bool skip = false;
10333f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map);
10334f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
10335ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
10336f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    const auto pd_state = GetPhysicalDeviceState(instance_data, physicalDevice);
10337f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
10338315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis    skip |= ValidatePhysicalDeviceQueueFamily(instance_data, pd_state, queueFamilyIndex, VALIDATION_ERROR_2f400a40,
10339f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus                                              "vkGetPhysicalDeviceXcbPresentationSupportKHR", "queueFamilyIndex");
10340f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
10341f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    lock.unlock();
10342f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
10343f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    if (skip) return VK_FALSE;
10344f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
10345f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    // Call down the call chain:
10346f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    VkBool32 result = instance_data->dispatch_table.GetPhysicalDeviceXcbPresentationSupportKHR(physicalDevice, queueFamilyIndex,
10347f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus                                                                                               connection, visual_id);
10348f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
10349f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    return result;
10350f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus}
10351cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif  // VK_USE_PLATFORM_XCB_KHR
10352747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
10353747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_XLIB_KHR
10354747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateXlibSurfaceKHR(VkInstance instance, const VkXlibSurfaceCreateInfoKHR *pCreateInfo,
10355bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                    const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
10356747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes    return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateXlibSurfaceKHR);
10357747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes}
10358f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
10359f25d461667ca2db55147d2be49f179945edf24dbPetr KrausVKAPI_ATTR VkBool32 VKAPI_CALL GetPhysicalDeviceXlibPresentationSupportKHR(VkPhysicalDevice physicalDevice,
10360f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus                                                                           uint32_t queueFamilyIndex, Display *dpy,
10361f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus                                                                           VisualID visualID) {
10362f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    bool skip = false;
10363f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map);
10364f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
10365ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
10366f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    const auto pd_state = GetPhysicalDeviceState(instance_data, physicalDevice);
10367f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
10368315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis    skip |= ValidatePhysicalDeviceQueueFamily(instance_data, pd_state, queueFamilyIndex, VALIDATION_ERROR_2f600a46,
10369f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus                                              "vkGetPhysicalDeviceXlibPresentationSupportKHR", "queueFamilyIndex");
10370f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
10371f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    lock.unlock();
10372f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
10373f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    if (skip) return VK_FALSE;
10374f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
10375f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    // Call down the call chain:
10376f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    VkBool32 result =
10377f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus        instance_data->dispatch_table.GetPhysicalDeviceXlibPresentationSupportKHR(physicalDevice, queueFamilyIndex, dpy, visualID);
10378f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
10379f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    return result;
10380f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus}
10381cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif  // VK_USE_PLATFORM_XLIB_KHR
10382747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes
1038340921785005eb449ec7c18229f0d84c879708b8aChris ForbesVKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface,
1038440921785005eb449ec7c18229f0d84c879708b8aChris Forbes                                                                       VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) {
1038556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    auto instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map);
1038640921785005eb449ec7c18229f0d84c879708b8aChris Forbes
10387ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
103889a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto physical_device_state = GetPhysicalDeviceState(instance_data, physicalDevice);
1038940921785005eb449ec7c18229f0d84c879708b8aChris Forbes    lock.unlock();
1039040921785005eb449ec7c18229f0d84c879708b8aChris Forbes
10391bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski    auto result =
10392bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        instance_data->dispatch_table.GetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, pSurfaceCapabilities);
1039340921785005eb449ec7c18229f0d84c879708b8aChris Forbes
1039440921785005eb449ec7c18229f0d84c879708b8aChris Forbes    if (result == VK_SUCCESS) {
1039540921785005eb449ec7c18229f0d84c879708b8aChris Forbes        physical_device_state->vkGetPhysicalDeviceSurfaceCapabilitiesKHRState = QUERY_DETAILS;
1039640921785005eb449ec7c18229f0d84c879708b8aChris Forbes        physical_device_state->surfaceCapabilities = *pSurfaceCapabilities;
1039740921785005eb449ec7c18229f0d84c879708b8aChris Forbes    }
1039840921785005eb449ec7c18229f0d84c879708b8aChris Forbes
1039940921785005eb449ec7c18229f0d84c879708b8aChris Forbes    return result;
1040040921785005eb449ec7c18229f0d84c879708b8aChris Forbes}
1040140921785005eb449ec7c18229f0d84c879708b8aChris Forbes
1040235b630211642e709485879a2e8859736f0ab16a0Mike Schuchardtstatic void PostCallRecordGetPhysicalDeviceSurfaceCapabilities2KHR(instance_layer_data *instanceData,
1040335b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt                                                                   VkPhysicalDevice physicalDevice,
1040435b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt                                                                   VkSurfaceCapabilities2KHR *pSurfaceCapabilities) {
10405ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
1040635b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    auto physicalDeviceState = GetPhysicalDeviceState(instanceData, physicalDevice);
1040735b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    physicalDeviceState->vkGetPhysicalDeviceSurfaceCapabilitiesKHRState = QUERY_DETAILS;
1040835b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    physicalDeviceState->surfaceCapabilities = pSurfaceCapabilities->surfaceCapabilities;
1040935b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt}
1041035b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt
1041135b630211642e709485879a2e8859736f0ab16a0Mike SchuchardtVKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice physicalDevice,
1041235b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt                                                                        const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
1041335b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt                                                                        VkSurfaceCapabilities2KHR *pSurfaceCapabilities) {
1041435b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    auto instanceData = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map);
1041535b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt
1041635b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    auto result =
1041735b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt        instanceData->dispatch_table.GetPhysicalDeviceSurfaceCapabilities2KHR(physicalDevice, pSurfaceInfo, pSurfaceCapabilities);
1041835b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt
1041935b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    if (result == VK_SUCCESS) {
1042035b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt        PostCallRecordGetPhysicalDeviceSurfaceCapabilities2KHR(instanceData, physicalDevice, pSurfaceCapabilities);
1042135b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    }
1042235b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt
1042335b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    return result;
1042435b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt}
1042535b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt
1042635b630211642e709485879a2e8859736f0ab16a0Mike Schuchardtstatic void PostCallRecordGetPhysicalDeviceSurfaceCapabilities2EXT(instance_layer_data *instanceData,
1042735b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt                                                                   VkPhysicalDevice physicalDevice,
1042835b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt                                                                   VkSurfaceCapabilities2EXT *pSurfaceCapabilities) {
10429ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
1043035b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    auto physicalDeviceState = GetPhysicalDeviceState(instanceData, physicalDevice);
1043135b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    physicalDeviceState->vkGetPhysicalDeviceSurfaceCapabilitiesKHRState = QUERY_DETAILS;
1043235b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    physicalDeviceState->surfaceCapabilities.minImageCount = pSurfaceCapabilities->minImageCount;
1043335b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    physicalDeviceState->surfaceCapabilities.maxImageCount = pSurfaceCapabilities->maxImageCount;
1043435b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    physicalDeviceState->surfaceCapabilities.currentExtent = pSurfaceCapabilities->currentExtent;
1043535b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    physicalDeviceState->surfaceCapabilities.minImageExtent = pSurfaceCapabilities->minImageExtent;
1043635b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    physicalDeviceState->surfaceCapabilities.maxImageExtent = pSurfaceCapabilities->maxImageExtent;
1043735b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    physicalDeviceState->surfaceCapabilities.maxImageArrayLayers = pSurfaceCapabilities->maxImageArrayLayers;
1043835b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    physicalDeviceState->surfaceCapabilities.supportedTransforms = pSurfaceCapabilities->supportedTransforms;
1043935b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    physicalDeviceState->surfaceCapabilities.currentTransform = pSurfaceCapabilities->currentTransform;
1044035b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    physicalDeviceState->surfaceCapabilities.supportedCompositeAlpha = pSurfaceCapabilities->supportedCompositeAlpha;
1044135b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    physicalDeviceState->surfaceCapabilities.supportedUsageFlags = pSurfaceCapabilities->supportedUsageFlags;
1044235b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt}
1044335b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt
1044435b630211642e709485879a2e8859736f0ab16a0Mike SchuchardtVKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceCapabilities2EXT(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface,
1044535b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt                                                                        VkSurfaceCapabilities2EXT *pSurfaceCapabilities) {
1044635b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    auto instanceData = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map);
1044735b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt
1044835b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    auto result =
1044935b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt        instanceData->dispatch_table.GetPhysicalDeviceSurfaceCapabilities2EXT(physicalDevice, surface, pSurfaceCapabilities);
1045035b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt
1045135b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    if (result == VK_SUCCESS) {
1045235b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt        PostCallRecordGetPhysicalDeviceSurfaceCapabilities2EXT(instanceData, physicalDevice, pSurfaceCapabilities);
1045335b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    }
1045435b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt
1045535b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    return result;
1045635b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt}
1045735b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt
10458418a8711f3301f3027a900bb45daaf0892f4e644Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex,
10459418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes                                                                  VkSurfaceKHR surface, VkBool32 *pSupported) {
10460f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    bool skip = false;
1046156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    auto instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map);
10462f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
10463ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
10464f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    const auto pd_state = GetPhysicalDeviceState(instance_data, physicalDevice);
104659a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto surface_state = GetSurfaceState(instance_data, surface);
10466f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
10467315b15c3d74eb1df11b992c2b9922cf98e939eb8Tobin Ehlis    skip |= ValidatePhysicalDeviceQueueFamily(instance_data, pd_state, queueFamilyIndex, VALIDATION_ERROR_2ee009ea,
10468f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus                                              "vkGetPhysicalDeviceSurfaceSupportKHR", "queueFamilyIndex");
10469f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
10470418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes    lock.unlock();
10471418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes
10472f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus    if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
10473f25d461667ca2db55147d2be49f179945edf24dbPetr Kraus
10474bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski    auto result =
10475bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        instance_data->dispatch_table.GetPhysicalDeviceSurfaceSupportKHR(physicalDevice, queueFamilyIndex, surface, pSupported);
10476418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes
10477418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes    if (result == VK_SUCCESS) {
104780bbc015828bdb99e85e6731ce92428557902701fPetr Kraus        surface_state->gpu_queue_support[{physicalDevice, queueFamilyIndex}] = (*pSupported == VK_TRUE);
10479418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes    }
10480418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes
10481418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes    return result;
10482418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes}
10483418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes
104849e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface,
104859e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes                                                                       uint32_t *pPresentModeCount,
104869e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes                                                                       VkPresentModeKHR *pPresentModes) {
104873251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
1048856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    auto instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map);
10489ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
104909e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes    // TODO: this isn't quite right. available modes may differ by surface AND physical device.
104919a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto physical_device_state = GetPhysicalDeviceState(instance_data, physicalDevice);
10492bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski    auto &call_state = physical_device_state->vkGetPhysicalDeviceSurfacePresentModesKHRState;
104939e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes
104949e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes    if (pPresentModes) {
104959e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes        // Compare the preliminary value of *pPresentModeCount with the value this time:
10496bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        auto prev_mode_count = (uint32_t)physical_device_state->present_modes.size();
104979e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes        switch (call_state) {
10498cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            case UNCALLED:
104993251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(
10500bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                    instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
105019b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                    HandleToUint64(physicalDevice), __LINE__, DEVLIMITS_MUST_QUERY_COUNT, "DL",
10502cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                    "vkGetPhysicalDeviceSurfacePresentModesKHR() called with non-NULL pPresentModeCount; but no prior positive "
10503cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                    "value has been seen for pPresentModeCount.");
10504cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                break;
10505cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            default:
10506cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                // both query count and query details
10507cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                if (*pPresentModeCount != prev_mode_count) {
105083251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT,
105099b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                    VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, HandleToUint64(physicalDevice), __LINE__,
105109b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                                    DEVLIMITS_COUNT_MISMATCH, "DL",
105113251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    "vkGetPhysicalDeviceSurfacePresentModesKHR() called with *pPresentModeCount (%u) that "
105123251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    "differs from the value "
105133251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    "(%u) that was returned when pPresentModes was NULL.",
105143251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                    *pPresentModeCount, prev_mode_count);
10515cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                }
10516cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                break;
105179e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes        }
105189e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes    }
105199e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes    lock.unlock();
105209e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes
105213251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
105229e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes
10523bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski    auto result = instance_data->dispatch_table.GetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, pPresentModeCount,
10524bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                                                        pPresentModes);
105259e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes
105269e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes    if (result == VK_SUCCESS || result == VK_INCOMPLETE) {
105279e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes        lock.lock();
105289e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes
105299e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes        if (*pPresentModeCount) {
10530cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            if (call_state < QUERY_COUNT) call_state = QUERY_COUNT;
105319e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes            if (*pPresentModeCount > physical_device_state->present_modes.size())
105329e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes                physical_device_state->present_modes.resize(*pPresentModeCount);
105339e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes        }
105349e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes        if (pPresentModes) {
10535cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            if (call_state < QUERY_DETAILS) call_state = QUERY_DETAILS;
105369e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes            for (uint32_t i = 0; i < *pPresentModeCount; i++) {
105379e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes                physical_device_state->present_modes[i] = pPresentModes[i];
105389e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes            }
105399e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes        }
105405faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes    }
105415faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes
105425faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes    return result;
105435faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes}
105445faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes
105455faa662f6859b01c72d79027abde363d5f10dcd7Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface,
105465faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes                                                                  uint32_t *pSurfaceFormatCount,
105475faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes                                                                  VkSurfaceFormatKHR *pSurfaceFormats) {
105483251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
1054956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    auto instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map);
10550ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
105519a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis    auto physical_device_state = GetPhysicalDeviceState(instance_data, physicalDevice);
10552bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski    auto &call_state = physical_device_state->vkGetPhysicalDeviceSurfaceFormatsKHRState;
105535faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes
105545faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes    if (pSurfaceFormats) {
10555bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski        auto prev_format_count = (uint32_t)physical_device_state->surface_formats.size();
105565faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes
105575faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes        switch (call_state) {
10558cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            case UNCALLED:
10559cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                // Since we haven't recorded a preliminary value of *pSurfaceFormatCount, that likely means that the application
10560cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                // didn't
10561cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                // previously call this function with a NULL value of pSurfaceFormats:
105623251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(
10563bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                    instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
105649b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                    HandleToUint64(physicalDevice), __LINE__, DEVLIMITS_MUST_QUERY_COUNT, "DL",
10565cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                    "vkGetPhysicalDeviceSurfaceFormatsKHR() called with non-NULL pSurfaceFormatCount; but no prior positive "
10566cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                    "value has been seen for pSurfaceFormats.");
10567cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                break;
10568cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            default:
10569cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                if (prev_format_count != *pSurfaceFormatCount) {
105703251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                    skip |= log_msg(
10571cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                        instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT,
105729b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                        VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, HandleToUint64(physicalDevice), __LINE__,
10573cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                        DEVLIMITS_COUNT_MISMATCH, "DL",
10574cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                        "vkGetPhysicalDeviceSurfaceFormatsKHR() called with non-NULL pSurfaceFormatCount, and with pSurfaceFormats "
10575cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                        "set "
10576cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                        "to "
10577cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                        "a value (%u) that is greater than the value (%u) that was returned when pSurfaceFormatCount was NULL.",
10578cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                        *pSurfaceFormatCount, prev_format_count);
10579cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                }
10580cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski                break;
105819e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes        }
105829e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes    }
105835faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes    lock.unlock();
105845faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes
105853251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
105869e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes
105875faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes    // Call down the call chain:
105885faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes    auto result = instance_data->dispatch_table.GetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, pSurfaceFormatCount,
105895faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes                                                                                   pSurfaceFormats);
105905faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes
105915faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes    if (result == VK_SUCCESS || result == VK_INCOMPLETE) {
105925faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes        lock.lock();
105935faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes
105945faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes        if (*pSurfaceFormatCount) {
10595cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            if (call_state < QUERY_COUNT) call_state = QUERY_COUNT;
105965faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes            if (*pSurfaceFormatCount > physical_device_state->surface_formats.size())
105975faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes                physical_device_state->surface_formats.resize(*pSurfaceFormatCount);
105985faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes        }
105995faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes        if (pSurfaceFormats) {
10600cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski            if (call_state < QUERY_DETAILS) call_state = QUERY_DETAILS;
106015faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes            for (uint32_t i = 0; i < *pSurfaceFormatCount; i++) {
106025faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes                physical_device_state->surface_formats[i] = pSurfaceFormats[i];
106035faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes            }
106045faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes        }
106055faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes    }
106069e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes    return result;
106079e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes}
106089e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes
1060935b630211642e709485879a2e8859736f0ab16a0Mike Schuchardtstatic void PostCallRecordGetPhysicalDeviceSurfaceFormats2KHR(instance_layer_data *instanceData, VkPhysicalDevice physicalDevice,
1061035b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt                                                              uint32_t *pSurfaceFormatCount, VkSurfaceFormat2KHR *pSurfaceFormats) {
10611ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
1061235b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    auto physicalDeviceState = GetPhysicalDeviceState(instanceData, physicalDevice);
1061335b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    if (*pSurfaceFormatCount) {
1061435b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt        if (physicalDeviceState->vkGetPhysicalDeviceSurfaceFormatsKHRState < QUERY_COUNT) {
1061535b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt            physicalDeviceState->vkGetPhysicalDeviceSurfaceFormatsKHRState = QUERY_COUNT;
1061635b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt        }
1061735b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt        if (*pSurfaceFormatCount > physicalDeviceState->surface_formats.size())
1061835b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt            physicalDeviceState->surface_formats.resize(*pSurfaceFormatCount);
1061935b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    }
1062035b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    if (pSurfaceFormats) {
1062135b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt        if (physicalDeviceState->vkGetPhysicalDeviceSurfaceFormatsKHRState < QUERY_DETAILS) {
1062235b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt            physicalDeviceState->vkGetPhysicalDeviceSurfaceFormatsKHRState = QUERY_DETAILS;
1062335b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt        }
1062435b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt        for (uint32_t i = 0; i < *pSurfaceFormatCount; i++) {
1062535b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt            physicalDeviceState->surface_formats[i] = pSurfaceFormats[i].surfaceFormat;
1062635b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt        }
1062735b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    }
1062835b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt}
1062935b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt
1063035b630211642e709485879a2e8859736f0ab16a0Mike SchuchardtVKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceFormats2KHR(VkPhysicalDevice physicalDevice,
1063135b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt                                                                   const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
1063235b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt                                                                   uint32_t *pSurfaceFormatCount,
1063335b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt                                                                   VkSurfaceFormat2KHR *pSurfaceFormats) {
1063435b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    auto instanceData = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map);
1063535b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    auto result = instanceData->dispatch_table.GetPhysicalDeviceSurfaceFormats2KHR(physicalDevice, pSurfaceInfo,
1063635b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt                                                                                   pSurfaceFormatCount, pSurfaceFormats);
1063735b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    if (result == VK_SUCCESS || result == VK_INCOMPLETE) {
1063835b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt        PostCallRecordGetPhysicalDeviceSurfaceFormats2KHR(instanceData, physicalDevice, pSurfaceFormatCount, pSurfaceFormats);
1063935b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    }
1064035b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt    return result;
1064135b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt}
1064235b630211642e709485879a2e8859736f0ab16a0Mike Schuchardt
10643bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateDebugReportCallbackEXT(VkInstance instance,
10644bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                            const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
10645bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                            const VkAllocationCallbacks *pAllocator,
10646bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                            VkDebugReportCallbackEXT *pMsgCallback) {
1064756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map);
106489172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes    VkResult res = instance_data->dispatch_table.CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
106495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    if (VK_SUCCESS == res) {
10650ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes        lock_guard_t lock(global_lock);
106518860b85a52096f9f9b28616bc37feed505497a54Chris Forbes        res = layer_create_msg_callback(instance_data->report_data, false, pCreateInfo, pAllocator, pMsgCallback);
106525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    }
106535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis    return res;
106545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
106555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
10656bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT msgCallback,
1065789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu                                                         const VkAllocationCallbacks *pAllocator) {
1065856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map);
106599172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes    instance_data->dispatch_table.DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
10660ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    lock_guard_t lock(global_lock);
106618860b85a52096f9f9b28616bc37feed505497a54Chris Forbes    layer_destroy_msg_callback(instance_data->report_data, msgCallback, pAllocator);
106625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
106635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
10664bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags,
10665bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                 VkDebugReportObjectTypeEXT objType, uint64_t object, size_t location,
10666bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                 int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
1066756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map);
106689172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes    instance_data->dispatch_table.DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
106695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
106705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
10671bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
10672a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu    return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
10673a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu}
10674a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu
10675bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
10676bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                              VkLayerProperties *pProperties) {
10677a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu    return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
10678a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu}
10679a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu
10680bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
10681bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                                    VkExtensionProperties *pProperties) {
10682a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu    if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
10683a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu        return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
10684a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu
10685a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu    return VK_ERROR_LAYER_NOT_PRESENT;
10686a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu}
10687a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu
10688bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName,
10689bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                                  uint32_t *pCount, VkExtensionProperties *pProperties) {
10690fe772548f7a48b12772483e8faecc956fb76eb42Chris Forbes    if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(1, device_extensions, pCount, pProperties);
10691a8f4a23b1e9c068717eda47cc583a93f447c77e3Chia-I Wu
10692a8f4a23b1e9c068717eda47cc583a93f447c77e3Chia-I Wu    assert(physicalDevice);
10693a8f4a23b1e9c068717eda47cc583a93f447c77e3Chia-I Wu
1069456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map);
106959172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes    return instance_data->dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
1069608939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu}
1069708939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu
10698582b6ed09649188d55ed3b6237352caf9f3384a9Mike WeiblenVKAPI_ATTR VkResult VKAPI_CALL EnumeratePhysicalDeviceGroupsKHX(
10699582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen    VkInstance instance, uint32_t *pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupPropertiesKHX *pPhysicalDeviceGroupProperties) {
107003251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski    bool skip = false;
10701582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen    instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map);
10702582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen
10703582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen    if (instance_data) {
10704582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen        // For this instance, flag when EnumeratePhysicalDeviceGroupsKHX goes to QUERY_COUNT and then QUERY_DETAILS.
10705582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen        if (NULL == pPhysicalDeviceGroupProperties) {
10706582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen            instance_data->vkEnumeratePhysicalDeviceGroupsState = QUERY_COUNT;
10707582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen        } else {
10708582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen            if (UNCALLED == instance_data->vkEnumeratePhysicalDeviceGroupsState) {
10709582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen                // Flag warning here. You can call this without having queried the count, but it may not be
10710582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen                // robust on platforms with multiple physical devices.
107113251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT,
107123251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, 0, __LINE__, DEVLIMITS_MISSING_QUERY_COUNT, "DL",
107133251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "Call sequence has vkEnumeratePhysicalDeviceGroupsKHX() w/ non-NULL "
107143251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "pPhysicalDeviceGroupProperties. You should first "
107153251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "call vkEnumeratePhysicalDeviceGroupsKHX() w/ NULL pPhysicalDeviceGroupProperties to query "
107163251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                                "pPhysicalDeviceGroupCount.");
10717582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen            } // TODO : Could also flag a warning if re-calling this function in QUERY_DETAILS state
10718582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen            else if (instance_data->physical_device_groups_count != *pPhysicalDeviceGroupCount) {
10719582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen                // Having actual count match count from app is not a requirement, so this can be a warning
107203251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                skip |=
10721582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen                    log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT,
107223251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_COUNT_MISMATCH, "DL",
107233251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "Call to vkEnumeratePhysicalDeviceGroupsKHX() w/ pPhysicalDeviceGroupCount value %u, but actual count "
107243251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            "supported by this instance is %u.",
107253251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski                            *pPhysicalDeviceGroupCount, instance_data->physical_device_groups_count);
10726582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen            }
10727582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen            instance_data->vkEnumeratePhysicalDeviceGroupsState = QUERY_DETAILS;
10728582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen        }
107293251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski        if (skip) {
10730582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen            return VK_ERROR_VALIDATION_FAILED_EXT;
10731582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen        }
10732582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen        VkResult result = instance_data->dispatch_table.EnumeratePhysicalDeviceGroupsKHX(instance, pPhysicalDeviceGroupCount,
10733582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen            pPhysicalDeviceGroupProperties);
10734582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen        if (NULL == pPhysicalDeviceGroupProperties) {
10735582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen            instance_data->physical_device_groups_count = *pPhysicalDeviceGroupCount;
10736582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen        } else if (result == VK_SUCCESS) { // Save physical devices
10737582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen            for (uint32_t i = 0; i < *pPhysicalDeviceGroupCount; i++) {
10738582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen                for (uint32_t j = 0; j < pPhysicalDeviceGroupProperties[i].physicalDeviceCount; j++) {
10739582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen                    VkPhysicalDevice cur_phys_dev = pPhysicalDeviceGroupProperties[i].physicalDevices[j];
10740582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen                    auto &phys_device_state = instance_data->physical_device_map[cur_phys_dev];
10741582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen                    phys_device_state.phys_device = cur_phys_dev;
10742582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen                    // Init actual features for each physical device
10743582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen                    instance_data->dispatch_table.GetPhysicalDeviceFeatures(cur_phys_dev, &phys_device_state.features);
10744582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen                }
10745582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen            }
10746582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen        }
10747582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen        return result;
10748582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen    } else {
10749582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen        log_msg(instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, 0, __LINE__,
107509b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                DEVLIMITS_INVALID_INSTANCE, "DL",
107519b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                "Invalid instance (0x%" PRIxLEAST64 ") passed into vkEnumeratePhysicalDeviceGroupsKHX().",
107529b6bedb9061a3ab94386ee9293da1dd43267a680Petr Kraus                HandleToUint64(instance));
10753582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen    }
10754582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen    return VK_ERROR_VALIDATION_FAILED_EXT;
10755582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen}
10756582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen
107576246f8feba03ddc787c31b3daa6a50d4ef01024fMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateDescriptorUpdateTemplateKHR(VkDevice device,
107586246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski                                                                 const VkDescriptorUpdateTemplateCreateInfoKHR *pCreateInfo,
107596246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski                                                                 const VkAllocationCallbacks *pAllocator,
107606246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski                                                                 VkDescriptorUpdateTemplateKHR *pDescriptorUpdateTemplate) {
107616246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
10762a538cd4fff983b172362b0bba58f984124481a1cMark Lobodzinski    VkResult result =
10763a538cd4fff983b172362b0bba58f984124481a1cMark Lobodzinski        dev_data->dispatch_table.CreateDescriptorUpdateTemplateKHR(device, pCreateInfo, pAllocator, pDescriptorUpdateTemplate);
107646246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski    if (VK_SUCCESS == result) {
10765ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes        lock_guard_t lock(global_lock);
107666246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski        // Shadow template createInfo for later updates
10767a538cd4fff983b172362b0bba58f984124481a1cMark Lobodzinski        safe_VkDescriptorUpdateTemplateCreateInfoKHR *local_create_info =
10768a538cd4fff983b172362b0bba58f984124481a1cMark Lobodzinski            new safe_VkDescriptorUpdateTemplateCreateInfoKHR(pCreateInfo);
107696246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski        std::unique_ptr<TEMPLATE_STATE> template_state(new TEMPLATE_STATE(*pDescriptorUpdateTemplate, local_create_info));
107706246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski        dev_data->desc_template_map[*pDescriptorUpdateTemplate] = std::move(template_state);
107716246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski    }
107726246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski    return result;
107736246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski}
107746246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski
107756246f8feba03ddc787c31b3daa6a50d4ef01024fMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyDescriptorUpdateTemplateKHR(VkDevice device,
107766246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski                                                              VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate,
107776246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski                                                              const VkAllocationCallbacks *pAllocator) {
107786246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
10779ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
107806246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski    dev_data->desc_template_map.erase(descriptorUpdateTemplate);
107816246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski    lock.unlock();
107826246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski    dev_data->dispatch_table.DestroyDescriptorUpdateTemplateKHR(device, descriptorUpdateTemplate, pAllocator);
107836246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski}
107846246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski
1078525f3712aed1cebdcb7c92eb25c5f1cc6e5986ac4Mark Lobodzinski// PostCallRecord* handles recording state updates following call down chain to UpdateDescriptorSetsWithTemplate()
1078625f3712aed1cebdcb7c92eb25c5f1cc6e5986ac4Mark Lobodzinskistatic void PostCallRecordUpdateDescriptorSetWithTemplateKHR(layer_data *device_data, VkDescriptorSet descriptorSet,
1078725f3712aed1cebdcb7c92eb25c5f1cc6e5986ac4Mark Lobodzinski                                                             VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate,
1078825f3712aed1cebdcb7c92eb25c5f1cc6e5986ac4Mark Lobodzinski                                                             const void *pData) {
1078967fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski    auto const template_map_entry = device_data->desc_template_map.find(descriptorUpdateTemplate);
1079067fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski    if (template_map_entry == device_data->desc_template_map.end()) {
1079167fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski        assert(0);
1079267fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski    }
1079367fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski
1079425f3712aed1cebdcb7c92eb25c5f1cc6e5986ac4Mark Lobodzinski    cvdescriptorset::PerformUpdateDescriptorSetsWithTemplateKHR(device_data, descriptorSet, template_map_entry->second, pData);
1079567fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski}
1079667fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski
107976246f8feba03ddc787c31b3daa6a50d4ef01024fMark LobodzinskiVKAPI_ATTR void VKAPI_CALL UpdateDescriptorSetWithTemplateKHR(VkDevice device, VkDescriptorSet descriptorSet,
107986246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski                                                              VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate,
107996246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski                                                              const void *pData) {
1080067fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski    layer_data *device_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1080167fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski    device_data->dispatch_table.UpdateDescriptorSetWithTemplateKHR(device, descriptorSet, descriptorUpdateTemplate, pData);
1080267fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski
1080367fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski    PostCallRecordUpdateDescriptorSetWithTemplateKHR(device_data, descriptorSet, descriptorUpdateTemplate, pData);
108046246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski}
108056246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski
108066246f8feba03ddc787c31b3daa6a50d4ef01024fMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdPushDescriptorSetWithTemplateKHR(VkCommandBuffer commandBuffer,
108076246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski                                                               VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate,
108086246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski                                                               VkPipelineLayout layout, uint32_t set, const void *pData) {
108096246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski    layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
108106246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski    dev_data->dispatch_table.CmdPushDescriptorSetWithTemplateKHR(commandBuffer, descriptorUpdateTemplate, layout, set, pData);
108116246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski}
108126246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski
10813991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinskistatic void PostCallRecordGetPhysicalDeviceDisplayPlanePropertiesKHR(instance_layer_data *instanceData,
10814991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                                                                     VkPhysicalDevice physicalDevice, uint32_t *pPropertyCount,
10815991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                                                                     VkDisplayPlanePropertiesKHR *pProperties) {
10816ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    unique_lock_t lock(global_lock);
10817991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    auto physical_device_state = GetPhysicalDeviceState(instanceData, physicalDevice);
10818991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski
10819991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    if (*pPropertyCount) {
108207c9b2aea1e047762ea9cff97ddd1fd33b5efc71dChris Forbes        if (physical_device_state->vkGetPhysicalDeviceDisplayPlanePropertiesKHRState < QUERY_COUNT) {
108217c9b2aea1e047762ea9cff97ddd1fd33b5efc71dChris Forbes            physical_device_state->vkGetPhysicalDeviceDisplayPlanePropertiesKHRState = QUERY_COUNT;
10822991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski        }
10823991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski        physical_device_state->display_plane_property_count = *pPropertyCount;
10824991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    }
10825991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    if (pProperties) {
108267c9b2aea1e047762ea9cff97ddd1fd33b5efc71dChris Forbes        if (physical_device_state->vkGetPhysicalDeviceDisplayPlanePropertiesKHRState < QUERY_DETAILS) {
108277c9b2aea1e047762ea9cff97ddd1fd33b5efc71dChris Forbes            physical_device_state->vkGetPhysicalDeviceDisplayPlanePropertiesKHRState = QUERY_DETAILS;
10828991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski        }
10829991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    }
10830991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski}
10831991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski
10832991f2555bc4f571e30b584937c7959805dff67c6Mark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceDisplayPlanePropertiesKHR(VkPhysicalDevice physicalDevice, uint32_t *pPropertyCount,
10833991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                                                                          VkDisplayPlanePropertiesKHR *pProperties) {
10834991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    VkResult result = VK_SUCCESS;
10835991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map);
10836991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski
10837991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    result = instance_data->dispatch_table.GetPhysicalDeviceDisplayPlanePropertiesKHR(physicalDevice, pPropertyCount, pProperties);
10838991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski
10839991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    if (result == VK_SUCCESS || result == VK_INCOMPLETE) {
10840991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski        PostCallRecordGetPhysicalDeviceDisplayPlanePropertiesKHR(instance_data, physicalDevice, pPropertyCount, pProperties);
10841991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    }
10842991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski
10843991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    return result;
10844991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski}
10845991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski
10846991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinskistatic bool ValidateGetPhysicalDeviceDisplayPlanePropertiesKHRQuery(instance_layer_data *instance_data,
10847991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                                                                    VkPhysicalDevice physicalDevice, uint32_t planeIndex,
10848991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                                                                    const char *api_name) {
10849991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    bool skip = false;
10850991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    auto physical_device_state = GetPhysicalDeviceState(instance_data, physicalDevice);
108517c9b2aea1e047762ea9cff97ddd1fd33b5efc71dChris Forbes    if (physical_device_state->vkGetPhysicalDeviceDisplayPlanePropertiesKHRState == UNCALLED) {
10852991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski        skip |= log_msg(
10853991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
10854991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            HandleToUint64(physicalDevice), __LINE__, SWAPCHAIN_GET_SUPPORTED_DISPLAYS_WITHOUT_QUERY, "DL",
10855991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            "Potential problem with calling %s() without first querying vkGetPhysicalDeviceDisplayPlanePropertiesKHR.", api_name);
10856991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    } else {
10857991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski        if (planeIndex >= physical_device_state->display_plane_property_count) {
10858991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            skip |= log_msg(
10859991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
10860991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                HandleToUint64(physicalDevice), __LINE__, VALIDATION_ERROR_29c009c2, "DL",
10861991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                "%s(): planeIndex must be in the range [0, %d] that was returned by vkGetPhysicalDeviceDisplayPlanePropertiesKHR. "
10862991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                "Do you have the plane index hardcoded? %s",
10863991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                api_name, physical_device_state->display_plane_property_count - 1, validation_error_map[VALIDATION_ERROR_29c009c2]);
10864991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski        }
10865991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    }
10866991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    return skip;
10867991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski}
10868991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski
10869991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinskistatic bool PreCallValidateGetDisplayPlaneSupportedDisplaysKHR(instance_layer_data *instance_data, VkPhysicalDevice physicalDevice,
10870991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                                                               uint32_t planeIndex) {
10871991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    bool skip = false;
10872ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    lock_guard_t lock(global_lock);
10873991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    skip |= ValidateGetPhysicalDeviceDisplayPlanePropertiesKHRQuery(instance_data, physicalDevice, planeIndex,
10874991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                                                                    "vkGetDisplayPlaneSupportedDisplaysKHR");
10875991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    return skip;
10876991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski}
10877991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski
10878991f2555bc4f571e30b584937c7959805dff67c6Mark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL GetDisplayPlaneSupportedDisplaysKHR(VkPhysicalDevice physicalDevice, uint32_t planeIndex,
10879991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                                                                   uint32_t *pDisplayCount, VkDisplayKHR *pDisplays) {
10880991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
10881991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map);
10882991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    bool skip = PreCallValidateGetDisplayPlaneSupportedDisplaysKHR(instance_data, physicalDevice, planeIndex);
10883991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    if (!skip) {
10884991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski        result =
10885991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski            instance_data->dispatch_table.GetDisplayPlaneSupportedDisplaysKHR(physicalDevice, planeIndex, pDisplayCount, pDisplays);
10886991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    }
10887991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    return result;
10888991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski}
10889991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski
10890991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinskistatic bool PreCallValidateGetDisplayPlaneCapabilitiesKHR(instance_layer_data *instance_data, VkPhysicalDevice physicalDevice,
10891991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                                                          uint32_t planeIndex) {
10892991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    bool skip = false;
10893ae7cdbc74057799801bb1d9a8203e38f75429a25Chris Forbes    lock_guard_t lock(global_lock);
10894991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    skip |= ValidateGetPhysicalDeviceDisplayPlanePropertiesKHRQuery(instance_data, physicalDevice, planeIndex,
10895991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                                                                    "vkGetDisplayPlaneCapabilitiesKHR");
10896991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    return skip;
10897991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski}
10898991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski
10899991f2555bc4f571e30b584937c7959805dff67c6Mark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL GetDisplayPlaneCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkDisplayModeKHR mode,
10900991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski                                                              uint32_t planeIndex, VkDisplayPlaneCapabilitiesKHR *pCapabilities) {
10901991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
10902991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map);
10903991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    bool skip = PreCallValidateGetDisplayPlaneCapabilitiesKHR(instance_data, physicalDevice, planeIndex);
10904991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski
10905991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    if (!skip) {
10906991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski        result = instance_data->dispatch_table.GetDisplayPlaneCapabilitiesKHR(physicalDevice, mode, planeIndex, pCapabilities);
10907991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    }
10908991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski
10909991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    return result;
10910991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski}
10911991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski
109126dd9a6bc380bc606441fb036974f0ddadff4d0c8Mark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL DebugMarkerSetObjectNameEXT(VkDevice device, const VkDebugMarkerObjectNameInfoEXT *pNameInfo) {
109131f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour    std::unique_lock<std::mutex> lock(global_lock);
109141f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour    layer_data *device_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
109151f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour    if (pNameInfo->pObjectName) {
109161f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour        device_data->report_data->debugObjectNameMap->insert(
109171f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour            std::make_pair<uint64_t, std::string>((uint64_t &&)pNameInfo->object, pNameInfo->pObjectName));
109181f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour    } else {
109191f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour        device_data->report_data->debugObjectNameMap->erase(pNameInfo->object);
109201f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour    }
109211f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour    lock.unlock();
109221f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour    VkResult result = device_data->dispatch_table.DebugMarkerSetObjectNameEXT(device, pNameInfo);
109231f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour    return result;
109241f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour}
109251f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour
109261f53907e108555555ac7cc8e0daf639279ca67d4Tony BarbourVKAPI_ATTR VkResult VKAPI_CALL DebugMarkerSetObjectTagEXT(VkDevice device, VkDebugMarkerObjectTagInfoEXT *pTagInfo) {
109271f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour    layer_data *device_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
109281f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour    VkResult result = device_data->dispatch_table.DebugMarkerSetObjectTagEXT(device, pTagInfo);
109291f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour    return result;
109301f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour}
109311f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour
109321f53907e108555555ac7cc8e0daf639279ca67d4Tony BarbourVKAPI_ATTR void VKAPI_CALL CmdDebugMarkerBeginEXT(VkCommandBuffer commandBuffer, VkDebugMarkerMarkerInfoEXT *pMarkerInfo) {
109331f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour    layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
109341f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour    device_data->dispatch_table.CmdDebugMarkerBeginEXT(commandBuffer, pMarkerInfo);
109351f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour}
109361f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour
109371f53907e108555555ac7cc8e0daf639279ca67d4Tony BarbourVKAPI_ATTR void VKAPI_CALL CmdDebugMarkerEndEXT(VkCommandBuffer commandBuffer) {
109381f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour    layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
109391f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour    device_data->dispatch_table.CmdDebugMarkerEndEXT(commandBuffer);
109401f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour}
109411f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour
109421f53907e108555555ac7cc8e0daf639279ca67d4Tony BarbourVKAPI_ATTR void VKAPI_CALL CmdDebugMarkerInsertEXT(VkCommandBuffer commandBuffer, VkDebugMarkerMarkerInfoEXT *pMarkerInfo) {
109431f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour    layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
109441f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour    device_data->dispatch_table.CmdDebugMarkerInsertEXT(commandBuffer, pMarkerInfo);
109451f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour}
109461f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour
109473616276bb0053c612c0a8d223e81ae3808b1b2c4Mark LobodzinskiVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName);
109483616276bb0053c612c0a8d223e81ae3808b1b2c4Mark LobodzinskiVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetPhysicalDeviceProcAddr(VkInstance instance, const char *funcName);
109493616276bb0053c612c0a8d223e81ae3808b1b2c4Mark LobodzinskiVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName);
109503616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski
109513616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski// Map of all APIs to be intercepted by this layer
10952804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardtstatic const std::unordered_map<std::string, void *> name_to_funcptr_map = {
109533616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetInstanceProcAddr", (void*)GetInstanceProcAddr},
109543616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vk_layerGetPhysicalDeviceProcAddr", (void*)GetPhysicalDeviceProcAddr},
109553616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetDeviceProcAddr", (void*)GetDeviceProcAddr},
109563616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateInstance", (void*)CreateInstance},
109573616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateDevice", (void*)CreateDevice},
109583616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkEnumeratePhysicalDevices", (void*)EnumeratePhysicalDevices},
109593616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetPhysicalDeviceQueueFamilyProperties", (void*)GetPhysicalDeviceQueueFamilyProperties},
109603616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroyInstance", (void*)DestroyInstance},
109613616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkEnumerateInstanceLayerProperties", (void*)EnumerateInstanceLayerProperties},
109623616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkEnumerateDeviceLayerProperties", (void*)EnumerateDeviceLayerProperties},
109633616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkEnumerateInstanceExtensionProperties", (void*)EnumerateInstanceExtensionProperties},
109643616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkEnumerateDeviceExtensionProperties", (void*)EnumerateDeviceExtensionProperties},
109653616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateDescriptorUpdateTemplateKHR", (void*)CreateDescriptorUpdateTemplateKHR},
109663616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroyDescriptorUpdateTemplateKHR", (void*)DestroyDescriptorUpdateTemplateKHR},
109673616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkUpdateDescriptorSetWithTemplateKHR", (void*)UpdateDescriptorSetWithTemplateKHR},
109683616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdPushDescriptorSetWithTemplateKHR", (void*)CmdPushDescriptorSetWithTemplateKHR},
1096943839a7f8cf2180734f7b8ed3514eda94a63107aMark Lobodzinski    {"vkCmdPushDescriptorSetKHR", (void*)CmdPushDescriptorSetKHR},
109703616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateSwapchainKHR", (void*)CreateSwapchainKHR},
109713616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroySwapchainKHR", (void*)DestroySwapchainKHR},
109723616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetSwapchainImagesKHR", (void*)GetSwapchainImagesKHR},
109733616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkAcquireNextImageKHR", (void*)AcquireNextImageKHR},
109743616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkQueuePresentKHR", (void*)QueuePresentKHR},
109753616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkQueueSubmit", (void*)QueueSubmit},
109763616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkWaitForFences", (void*)WaitForFences},
109773616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetFenceStatus", (void*)GetFenceStatus},
109783616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkQueueWaitIdle", (void*)QueueWaitIdle},
109793616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDeviceWaitIdle", (void*)DeviceWaitIdle},
109803616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetDeviceQueue", (void*)GetDeviceQueue},
109813616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroyDevice", (void*)DestroyDevice},
109823616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroyFence", (void*)DestroyFence},
109833616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkResetFences", (void*)ResetFences},
109843616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroySemaphore", (void*)DestroySemaphore},
109853616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroyEvent", (void*)DestroyEvent},
109863616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroyQueryPool", (void*)DestroyQueryPool},
109873616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroyBuffer", (void*)DestroyBuffer},
109883616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroyBufferView", (void*)DestroyBufferView},
109893616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroyImage", (void*)DestroyImage},
109903616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroyImageView", (void*)DestroyImageView},
109913616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroyShaderModule", (void*)DestroyShaderModule},
109923616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroyPipeline", (void*)DestroyPipeline},
109933616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroyPipelineLayout", (void*)DestroyPipelineLayout},
109943616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroySampler", (void*)DestroySampler},
109953616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroyDescriptorSetLayout", (void*)DestroyDescriptorSetLayout},
109963616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroyDescriptorPool", (void*)DestroyDescriptorPool},
109973616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroyFramebuffer", (void*)DestroyFramebuffer},
109983616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroyRenderPass", (void*)DestroyRenderPass},
109993616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateBuffer", (void*)CreateBuffer},
110003616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateBufferView", (void*)CreateBufferView},
110013616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateImage", (void*)CreateImage},
110023616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateImageView", (void*)CreateImageView},
110033616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateFence", (void*)CreateFence},
110043616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreatePipelineCache", (void*)CreatePipelineCache},
110053616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroyPipelineCache", (void*)DestroyPipelineCache},
110063616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetPipelineCacheData", (void*)GetPipelineCacheData},
110073616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkMergePipelineCaches", (void*)MergePipelineCaches},
110083616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateGraphicsPipelines", (void*)CreateGraphicsPipelines},
110093616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateComputePipelines", (void*)CreateComputePipelines},
110103616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateSampler", (void*)CreateSampler},
110113616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateDescriptorSetLayout", (void*)CreateDescriptorSetLayout},
110123616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreatePipelineLayout", (void*)CreatePipelineLayout},
110133616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateDescriptorPool", (void*)CreateDescriptorPool},
110143616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkResetDescriptorPool", (void*)ResetDescriptorPool},
110153616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkAllocateDescriptorSets", (void*)AllocateDescriptorSets},
110163616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkFreeDescriptorSets", (void*)FreeDescriptorSets},
110173616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkUpdateDescriptorSets", (void*)UpdateDescriptorSets},
110183616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateCommandPool", (void*)CreateCommandPool},
110193616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroyCommandPool", (void*)DestroyCommandPool},
110203616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkResetCommandPool", (void*)ResetCommandPool},
110213616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateQueryPool", (void*)CreateQueryPool},
110223616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkAllocateCommandBuffers", (void*)AllocateCommandBuffers},
110233616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkFreeCommandBuffers", (void*)FreeCommandBuffers},
110243616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkBeginCommandBuffer", (void*)BeginCommandBuffer},
110253616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkEndCommandBuffer", (void*)EndCommandBuffer},
110263616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkResetCommandBuffer", (void*)ResetCommandBuffer},
110273616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdBindPipeline", (void*)CmdBindPipeline},
110283616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdSetViewport", (void*)CmdSetViewport},
110293616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdSetScissor", (void*)CmdSetScissor},
110303616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdSetLineWidth", (void*)CmdSetLineWidth},
110313616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdSetDepthBias", (void*)CmdSetDepthBias},
110323616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdSetBlendConstants", (void*)CmdSetBlendConstants},
110333616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdSetDepthBounds", (void*)CmdSetDepthBounds},
110343616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdSetStencilCompareMask", (void*)CmdSetStencilCompareMask},
110353616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdSetStencilWriteMask", (void*)CmdSetStencilWriteMask},
110363616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdSetStencilReference", (void*)CmdSetStencilReference},
110373616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdBindDescriptorSets", (void*)CmdBindDescriptorSets},
110383616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdBindVertexBuffers", (void*)CmdBindVertexBuffers},
110393616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdBindIndexBuffer", (void*)CmdBindIndexBuffer},
110403616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdDraw", (void*)CmdDraw},
110413616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdDrawIndexed", (void*)CmdDrawIndexed},
110423616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdDrawIndirect", (void*)CmdDrawIndirect},
110433616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdDrawIndexedIndirect", (void*)CmdDrawIndexedIndirect},
110443616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdDispatch", (void*)CmdDispatch},
110453616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdDispatchIndirect", (void*)CmdDispatchIndirect},
110463616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdCopyBuffer", (void*)CmdCopyBuffer},
110473616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdCopyImage", (void*)CmdCopyImage},
110483616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdBlitImage", (void*)CmdBlitImage},
110493616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdCopyBufferToImage", (void*)CmdCopyBufferToImage},
110503616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdCopyImageToBuffer", (void*)CmdCopyImageToBuffer},
110513616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdUpdateBuffer", (void*)CmdUpdateBuffer},
110523616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdFillBuffer", (void*)CmdFillBuffer},
110533616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdClearColorImage", (void*)CmdClearColorImage},
110543616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdClearDepthStencilImage", (void*)CmdClearDepthStencilImage},
110553616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdClearAttachments", (void*)CmdClearAttachments},
110563616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdResolveImage", (void*)CmdResolveImage},
110573616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetImageSubresourceLayout", (void*)GetImageSubresourceLayout},
110583616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdSetEvent", (void*)CmdSetEvent},
110593616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdResetEvent", (void*)CmdResetEvent},
110603616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdWaitEvents", (void*)CmdWaitEvents},
110613616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdPipelineBarrier", (void*)CmdPipelineBarrier},
110623616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdBeginQuery", (void*)CmdBeginQuery},
110633616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdEndQuery", (void*)CmdEndQuery},
110643616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdResetQueryPool", (void*)CmdResetQueryPool},
110653616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdCopyQueryPoolResults", (void*)CmdCopyQueryPoolResults},
110663616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdPushConstants", (void*)CmdPushConstants},
110673616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdWriteTimestamp", (void*)CmdWriteTimestamp},
110683616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateFramebuffer", (void*)CreateFramebuffer},
110693616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateShaderModule", (void*)CreateShaderModule},
110703616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateRenderPass", (void*)CreateRenderPass},
110713616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdBeginRenderPass", (void*)CmdBeginRenderPass},
110723616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdNextSubpass", (void*)CmdNextSubpass},
110733616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdEndRenderPass", (void*)CmdEndRenderPass},
110743616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCmdExecuteCommands", (void*)CmdExecuteCommands},
110751f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour    {"vkCmdDebugMarkerBeginEXT", (void*)CmdDebugMarkerBeginEXT},
110761f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour    {"vkCmdDebugMarkerEndEXT", (void*)CmdDebugMarkerEndEXT},
110771f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour    {"vkCmdDebugMarkerInsertEXT", (void*)CmdDebugMarkerInsertEXT},
110781f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour    {"vkDebugMarkerSetObjectNameEXT", (void*)DebugMarkerSetObjectNameEXT},
110791f53907e108555555ac7cc8e0daf639279ca67d4Tony Barbour    {"vkDebugMarkerSetObjectTagEXT", (void*)DebugMarkerSetObjectTagEXT},
110803616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkSetEvent", (void*)SetEvent},
110813616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkMapMemory", (void*)MapMemory},
110823616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkUnmapMemory", (void*)UnmapMemory},
110833616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkFlushMappedMemoryRanges", (void*)FlushMappedMemoryRanges},
110843616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkInvalidateMappedMemoryRanges", (void*)InvalidateMappedMemoryRanges},
110853616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkAllocateMemory", (void*)AllocateMemory},
110863616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkFreeMemory", (void*)FreeMemory},
110873616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkBindBufferMemory", (void*)BindBufferMemory},
110883616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetBufferMemoryRequirements", (void*)GetBufferMemoryRequirements},
110893616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetImageMemoryRequirements", (void*)GetImageMemoryRequirements},
110903616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetQueryPoolResults", (void*)GetQueryPoolResults},
110913616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkBindImageMemory", (void*)BindImageMemory},
110923616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkQueueBindSparse", (void*)QueueBindSparse},
110933616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateSemaphore", (void*)CreateSemaphore},
110943616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateEvent", (void*)CreateEvent},
110953616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski#ifdef VK_USE_PLATFORM_ANDROID_KHR
110963616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateAndroidSurfaceKHR", (void*)CreateAndroidSurfaceKHR},
110973616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski#endif
110983616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski#ifdef VK_USE_PLATFORM_MIR_KHR
110993616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateMirSurfaceKHR", (void*)CreateMirSurfaceKHR},
111003616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetPhysicalDeviceMirPresentationSupportKHR", (void*)GetPhysicalDeviceMirPresentationSupportKHR},
111013616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski#endif
111023616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski#ifdef VK_USE_PLATFORM_WAYLAND_KHR
111033616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateWaylandSurfaceKHR", (void*)CreateWaylandSurfaceKHR},
111043616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetPhysicalDeviceWaylandPresentationSupportKHR", (void*)GetPhysicalDeviceWaylandPresentationSupportKHR},
111053616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski#endif
111063616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski#ifdef VK_USE_PLATFORM_WIN32_KHR
111073616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateWin32SurfaceKHR", (void*)CreateWin32SurfaceKHR},
111083616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetPhysicalDeviceWin32PresentationSupportKHR", (void*)GetPhysicalDeviceWin32PresentationSupportKHR},
1110906d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt    {"vkImportSemaphoreWin32HandleKHR", (void*)ImportSemaphoreWin32HandleKHR},
1111006d5c171f0bb0acbed8120af6bac43f13a869e3fMike Schuchardt    {"vkGetSemaphoreWin32HandleKHR", (void*)GetSemaphoreWin32HandleKHR},
11111804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt    {"vkImportFenceWin32HandleKHR", (void*)ImportFenceWin32HandleKHR},
11112804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt    {"vkGetFenceWin32HandleKHR", (void*)GetFenceWin32HandleKHR},
111133616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski#endif
111143616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski#ifdef VK_USE_PLATFORM_XCB_KHR
111153616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateXcbSurfaceKHR", (void*)CreateXcbSurfaceKHR},
111163616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetPhysicalDeviceXcbPresentationSupportKHR", (void*)GetPhysicalDeviceXcbPresentationSupportKHR},
111173616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski#endif
111183616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski#ifdef VK_USE_PLATFORM_XLIB_KHR
111193616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateXlibSurfaceKHR", (void*)CreateXlibSurfaceKHR},
111203616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetPhysicalDeviceXlibPresentationSupportKHR", (void*)GetPhysicalDeviceXlibPresentationSupportKHR},
111213616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski#endif
111223616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateDisplayPlaneSurfaceKHR", (void*)CreateDisplayPlaneSurfaceKHR},
111233616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroySurfaceKHR", (void*)DestroySurfaceKHR},
111243616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetPhysicalDeviceSurfaceCapabilitiesKHR", (void*)GetPhysicalDeviceSurfaceCapabilitiesKHR},
111253616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetPhysicalDeviceSurfaceCapabilities2KHR", (void*)GetPhysicalDeviceSurfaceCapabilities2KHR},
111263616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetPhysicalDeviceSurfaceCapabilities2EXT", (void*)GetPhysicalDeviceSurfaceCapabilities2EXT},
111273616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetPhysicalDeviceSurfaceSupportKHR", (void*)GetPhysicalDeviceSurfaceSupportKHR},
111283616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetPhysicalDeviceSurfacePresentModesKHR", (void*)GetPhysicalDeviceSurfacePresentModesKHR},
111293616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetPhysicalDeviceSurfaceFormatsKHR", (void*)GetPhysicalDeviceSurfaceFormatsKHR},
111303616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetPhysicalDeviceSurfaceFormats2KHR", (void*)GetPhysicalDeviceSurfaceFormats2KHR},
111313616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkGetPhysicalDeviceQueueFamilyProperties2KHR", (void*)GetPhysicalDeviceQueueFamilyProperties2KHR},
111323616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkEnumeratePhysicalDeviceGroupsKHX", (void*)EnumeratePhysicalDeviceGroupsKHX},
111333616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkCreateDebugReportCallbackEXT", (void*)CreateDebugReportCallbackEXT},
111343616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDestroyDebugReportCallbackEXT", (void*)DestroyDebugReportCallbackEXT},
111353616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    {"vkDebugReportMessageEXT", (void*)DebugReportMessageEXT},
11136991f2555bc4f571e30b584937c7959805dff67c6Mark Lobodzinski    {"vkGetPhysicalDeviceDisplayPlanePropertiesKHR", (void*)GetPhysicalDeviceDisplayPlanePropertiesKHR},
11137c8fe10051b18a353adf7e5a6f015b12deaeffab4Mike Schuchardt    {"vkGetDisplayPlaneSupportedDisplaysKHR", (void*)GetDisplayPlaneSupportedDisplaysKHR},
11138c8fe10051b18a353adf7e5a6f015b12deaeffab4Mike Schuchardt    {"vkGetDisplayPlaneCapabilitiesKHR", (void*)GetDisplayPlaneCapabilitiesKHR},
1113916f39f23c20176b9ff809d10d76b62663e1adabdMike Schuchardt    {"vkImportSemaphoreFdKHR", (void*)ImportSemaphoreFdKHR},
1114016f39f23c20176b9ff809d10d76b62663e1adabdMike Schuchardt    {"vkGetSemaphoreFdKHR", (void*)GetSemaphoreFdKHR},
11141804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt    {"vkImportFenceFdKHR", (void*)ImportFenceFdKHR},
11142804e95a8a6a78f03a0325a78fd2b250a575ce3ceMike Schuchardt    {"vkGetFenceFdKHR", (void*)GetFenceFdKHR},
11143fe772548f7a48b12772483e8faecc956fb76eb42Chris Forbes    {"vkCreateValidationCacheEXT", (void*)CreateValidationCacheEXT},
11144fe772548f7a48b12772483e8faecc956fb76eb42Chris Forbes    {"vkDestroyValidationCacheEXT", (void*)DestroyValidationCacheEXT},
11145fe772548f7a48b12772483e8faecc956fb76eb42Chris Forbes    {"vkGetValidationCacheDataEXT", (void*)GetValidationCacheDataEXT},
11146fe772548f7a48b12772483e8faecc956fb76eb42Chris Forbes    {"vkMergeValidationCachesEXT", (void*)MergeValidationCachesEXT},
111473616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski};
11148b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young
111493616276bb0053c612c0a8d223e81ae3808b1b2c4Mark LobodzinskiVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
111503616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    assert(device);
111513616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    layer_data *device_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
111525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
111533616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    // Is API to be intercepted by this layer?
111543616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    const auto &item = name_to_funcptr_map.find(funcName);
111553616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    if (item != name_to_funcptr_map.end()) {
111563616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski        return reinterpret_cast<PFN_vkVoidFunction>(item->second);
111573616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    }
1115809a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu
111593616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    auto &table = device_data->dispatch_table;
11160cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (!table.GetDeviceProcAddr) return nullptr;
111613616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    return table.GetDeviceProcAddr(device, funcName);
111625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
111635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis
1116489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
111653616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    instance_layer_data *instance_data;
111663616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    // Is API to be intercepted by this layer?
111673616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    const auto &item = name_to_funcptr_map.find(funcName);
111683616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    if (item != name_to_funcptr_map.end()) {
111693616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski        return reinterpret_cast<PFN_vkVoidFunction>(item->second);
111703616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    }
11171b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young
111723616276bb0053c612c0a8d223e81ae3808b1b2c4Mark Lobodzinski    instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map);
111734a0754042cf090e131e9e769d8a3633c228625beChris Forbes    auto &table = instance_data->dispatch_table;
11174cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (!table.GetInstanceProcAddr) return nullptr;
111754a0754042cf090e131e9e769d8a3633c228625beChris Forbes    return table.GetInstanceProcAddr(instance, funcName);
111765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}
1117708939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu
11178b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark YoungVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetPhysicalDeviceProcAddr(VkInstance instance, const char *funcName) {
11179b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young    assert(instance);
1118056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis    instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map);
11181b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young
11182b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young    auto &table = instance_data->dispatch_table;
11183cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    if (!table.GetPhysicalDeviceProcAddr) return nullptr;
11184b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young    return table.GetPhysicalDeviceProcAddr(instance, funcName);
11185b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young}
11186b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young
11187cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski}  // namespace core_validation
11188d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu
11189a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu// loader-layer interface v0, just wrappers since there is only a layer
11190d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu
11191bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
11192bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                                                      VkExtensionProperties *pProperties) {
11193a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu    return core_validation::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
1119408939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu}
1119508939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu
11196bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
11197bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                                                  VkLayerProperties *pProperties) {
11198a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu    return core_validation::EnumerateInstanceLayerProperties(pCount, pProperties);
1119908939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu}
1120008939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu
11201bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
11202bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                                                VkLayerProperties *pProperties) {
11203a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu    // the layer command handles VK_NULL_HANDLE just fine internally
11204a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu    assert(physicalDevice == VK_NULL_HANDLE);
11205a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu    return core_validation::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
11206d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu}
11207d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu
11208d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I WuVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
11209d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu                                                                                    const char *pLayerName, uint32_t *pCount,
11210d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu                                                                                    VkExtensionProperties *pProperties) {
11211a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu    // the layer command handles VK_NULL_HANDLE just fine internally
11212a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu    assert(physicalDevice == VK_NULL_HANDLE);
11213a8f4a23b1e9c068717eda47cc583a93f447c77e3Chia-I Wu    return core_validation::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
11214d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu}
11215d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu
11216d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I WuVK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
1121789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu    return core_validation::GetDeviceProcAddr(dev, funcName);
11218d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu}
11219d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu
11220d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I WuVK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
1122189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu    return core_validation::GetInstanceProcAddr(instance, funcName);
1122208939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu}
11223b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young
11224bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance,
11225bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski                                                                                           const char *funcName) {
11226b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young    return core_validation::GetPhysicalDeviceProcAddr(instance, funcName);
11227b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young}
11228b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young
11229b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark YoungVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) {
11230b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young    assert(pVersionStruct != NULL);
11231b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young    assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT);
11232b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young
11233b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young    // Fill in the function pointers if our version is at least capable of having the structure contain them.
11234b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young    if (pVersionStruct->loaderLayerInterfaceVersion >= 2) {
11235b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young        pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr;
11236b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young        pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr;
11237b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young        pVersionStruct->pfnGetPhysicalDeviceProcAddr = vk_layerGetPhysicalDeviceProcAddr;
11238b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young    }
11239b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young
11240b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young    if (pVersionStruct->loaderLayerInterfaceVersion < CURRENT_LOADER_LAYER_INTERFACE_VERSION) {
11241b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young        core_validation::loader_layer_if_version = pVersionStruct->loaderLayerInterfaceVersion;
11242b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young    } else if (pVersionStruct->loaderLayerInterfaceVersion > CURRENT_LOADER_LAYER_INTERFACE_VERSION) {
11243b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young        pVersionStruct->loaderLayerInterfaceVersion = CURRENT_LOADER_LAYER_INTERFACE_VERSION;
11244b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young    }
11245b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young
11246b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young    return VK_SUCCESS;
11247b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young}
11248