core_validation.cpp revision 7992c34b28dd617787f0e4d34fd023f894495edb
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 <SPIRV/spirv.hpp> 4094c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis#include <algorithm> 4194c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis#include <assert.h> 4294c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis#include <iostream> 4394c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis#include <list> 4494c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis#include <map> 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> 52dd725b03ae4d1296a722d0ec5c9fe63941cabe4bChris Forbes#include <tuple> 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" 655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#include "vk_layer_table.h" 665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#include "vk_layer_data.h" 675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#include "vk_layer_extension_utils.h" 685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#include "vk_layer_utils.h" 69b1f65702539fd041337fccd493dc6d38dd2a603eChris Forbes#include "spirv-tools/libspirv.h" 705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#if defined __ANDROID__ 725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#include <android/log.h> 735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#define LOGCONSOLE(...) ((void)__android_log_print(ANDROID_LOG_INFO, "DS", __VA_ARGS__)) 745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#else 75cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#define LOGCONSOLE(...) \ 76cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski { \ 77cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski printf(__VA_ARGS__); \ 78cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski printf("\n"); \ 79c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine } 805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#endif 815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 82d147a5463f8581604ca542aa1a44a27e512e0f60Mike Stroyan// This intentionally includes a cpp file 83d147a5463f8581604ca542aa1a44a27e512e0f60Mike Stroyan#include "vk_safe_struct.cpp" 84d147a5463f8581604ca542aa1a44a27e512e0f60Mike Stroyan 85d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wunamespace core_validation { 86d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu 875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisusing std::unordered_map; 885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisusing std::unordered_set; 890c55adf45a81f44300db04ec71a797d790ef103cTobin Ehlisusing std::unique_ptr; 900c55adf45a81f44300db04ec71a797d790ef103cTobin Ehlisusing std::vector; 910c55adf45a81f44300db04ec71a797d790ef103cTobin Ehlisusing std::string; 920c55adf45a81f44300db04ec71a797d790ef103cTobin Ehlisusing std::stringstream; 930c55adf45a81f44300db04ec71a797d790ef103cTobin Ehlisusing std::max; 945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// WSI Image Objects bypass usual Image Object creation methods. A special Memory 965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Object value will be used to identify them internally. 975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic const VkDeviceMemory MEMTRACKER_SWAP_CHAIN_IMAGE_KEY = (VkDeviceMemory)(-1); 98888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis// 2nd special memory handle used to flag object as unbound from memory 99888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlisstatic const VkDeviceMemory MEMORY_UNBOUND = VkDeviceMemory(~((uint64_t)(0)) - 1); 100b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis 1012e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill// A special value of (0xFFFFFFFF, 0xFFFFFFFF) indicates that the surface size will be determined 1022e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill// by the extent of a swapchain targeting the surface. 1032e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madillstatic const uint32_t kSurfaceSizeFromSwapchain = 0xFFFFFFFFu; 1042e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill 1055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstruct devExts { 106e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool wsi_enabled; 107c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young bool wsi_display_swapchain_enabled; 108bee1d36c54af112766d4e8552ad302f39290683aMark Lobodzinski bool nv_glsl_shader_enabled; 1093f687bf405355f3eec6bd1bc0e8d04daba37a0f9Tobin Ehlis unordered_map<VkSwapchainKHR, unique_ptr<SWAPCHAIN_NODE>> swapchainMap; 1105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unordered_map<VkImage, VkSwapchainKHR> imageToSwapchainMap; 1115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}; 1125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// fwd decls 1145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstruct shader_module; 1155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 116f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbesstruct instance_layer_data { 117d3578035fec44db2380099c2f59d3e4d8e0b98d6Chris Forbes VkInstance instance = VK_NULL_HANDLE; 118d3578035fec44db2380099c2f59d3e4d8e0b98d6Chris Forbes debug_report_data *report_data = nullptr; 1195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::vector<VkDebugReportCallbackEXT> logging_callback; 1209172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes VkLayerInstanceDispatchTable dispatch_table; 1219172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes 122219f00ffed576643641976122fa1db8e5fce5dc1Chris Forbes CALL_STATE vkEnumeratePhysicalDevicesState = UNCALLED; 123219f00ffed576643641976122fa1db8e5fce5dc1Chris Forbes uint32_t physical_devices_count = 0; 124b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young CALL_STATE vkEnumeratePhysicalDeviceGroupsState = UNCALLED; 125b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young uint32_t physical_device_groups_count = 0; 126219f00ffed576643641976122fa1db8e5fce5dc1Chris Forbes CHECK_DISABLED disabled = {}; 127219f00ffed576643641976122fa1db8e5fce5dc1Chris Forbes 128f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbes unordered_map<VkPhysicalDevice, PHYSICAL_DEVICE_STATE> physical_device_map; 129747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes unordered_map<VkSurfaceKHR, SURFACE_STATE> surface_map; 130747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 131747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes bool surfaceExtensionEnabled = false; 132747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes bool displayExtensionEnabled = false; 133747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes bool androidSurfaceExtensionEnabled = false; 134747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes bool mirSurfaceExtensionEnabled = false; 135747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes bool waylandSurfaceExtensionEnabled = false; 136747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes bool win32SurfaceExtensionEnabled = false; 137747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes bool xcbSurfaceExtensionEnabled = false; 138747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes bool xlibSurfaceExtensionEnabled = false; 139f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbes}; 140f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbes 141f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbesstruct layer_data { 142f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbes debug_report_data *report_data = nullptr; 1434a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkLayerDispatchTable dispatch_table; 14494c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis 145d3578035fec44db2380099c2f59d3e4d8e0b98d6Chris Forbes devExts device_extensions = {}; 146cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski unordered_set<VkQueue> queues; // All queues under given device 1475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Global set of all cmdBuffers that are inFlight on this device 1485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unordered_set<VkCommandBuffer> globalInFlightCmdBuffers; 1495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Layer specific data 150d31a44af6da568692a73201825459689c9431867Tobin Ehlis unordered_map<VkSampler, unique_ptr<SAMPLER_STATE>> samplerMap; 15179fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis unordered_map<VkImageView, unique_ptr<IMAGE_VIEW_STATE>> imageViewMap; 1521facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis unordered_map<VkImage, unique_ptr<IMAGE_STATE>> imageMap; 15339267c0c27b8f032f05a6747eb02d4508247fdc1Tobin Ehlis unordered_map<VkBufferView, unique_ptr<BUFFER_VIEW_STATE>> bufferViewMap; 1545cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis unordered_map<VkBuffer, unique_ptr<BUFFER_STATE>> bufferMap; 1554c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis unordered_map<VkPipeline, PIPELINE_STATE *> pipelineMap; 1568d6a38de0389036581ada119e548180c614fe0efChris Forbes unordered_map<VkCommandPool, COMMAND_POOL_NODE> commandPoolMap; 157a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis unordered_map<VkDescriptorPool, DESCRIPTOR_POOL_STATE *> descriptorPoolMap; 158397d27da37095073c8b86f9ff5289d0a39ce486eTobin Ehlis unordered_map<VkDescriptorSet, cvdescriptorset::DescriptorSet *> setMap; 159cb9ce9e05b8e939d3da35c64997c70049877f4feTobin Ehlis unordered_map<VkDescriptorSetLayout, cvdescriptorset::DescriptorSetLayout *> descriptorSetLayoutMap; 1605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unordered_map<VkPipelineLayout, PIPELINE_LAYOUT_NODE> pipelineLayoutMap; 16157fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis unordered_map<VkDeviceMemory, unique_ptr<DEVICE_MEM_INFO>> memObjMap; 1625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unordered_map<VkFence, FENCE_NODE> fenceMap; 16336c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlis unordered_map<VkQueue, QUEUE_STATE> queueMap; 1644710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis unordered_map<VkEvent, EVENT_STATE> eventMap; 1655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unordered_map<QueryObject, bool> queryToStateMap; 1665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unordered_map<VkQueryPool, QUERY_POOL_NODE> queryPoolMap; 1675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unordered_map<VkSemaphore, SEMAPHORE_NODE> semaphoreMap; 16872d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis unordered_map<VkCommandBuffer, GLOBAL_CB_NODE *> commandBufferMap; 169c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis unordered_map<VkFramebuffer, unique_ptr<FRAMEBUFFER_STATE>> frameBufferMap; 1705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unordered_map<VkImage, vector<ImageSubresourcePair>> imageSubresourceMap; 1715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unordered_map<ImageSubresourcePair, IMAGE_LAYOUT_NODE> imageLayoutMap; 172127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis unordered_map<VkRenderPass, unique_ptr<RENDER_PASS_STATE>> renderPassMap; 173918c283ac4f8c604b79abd0c8b5706d2a7352a34Chris Forbes unordered_map<VkShaderModule, unique_ptr<shader_module>> shaderModuleMap; 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 = {}; 1855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}; 1865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 187b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis// TODO : Do we need to guard access to layer_data_map w/ lock? 188b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlisstatic unordered_map<void *, layer_data *> layer_data_map; 189f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbesstatic unordered_map<void *, instance_layer_data *> instance_layer_data_map; 190b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis 191b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Youngstatic uint32_t loader_layer_if_version = CURRENT_LOADER_LAYER_INTERFACE_VERSION; 192b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 193e11120777bcd1543455d1de54b89292879bcd2bbChia-I Wustatic const VkLayerProperties global_layer = { 194f1ea418f193d10a8455cdf47e0eeeeb1f4d8b5bfJon Ashburn "VK_LAYER_LUNARG_core_validation", VK_LAYER_API_VERSION, 1, "LunarG Validation Layer", 195e11120777bcd1543455d1de54b89292879bcd2bbChia-I Wu}; 1965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 197cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskitemplate <class TCreateInfo> 198cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskivoid ValidateLayerOrdering(const TCreateInfo &createInfo) { 1995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool foundLayer = false; 2005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < createInfo.enabledLayerCount; ++i) { 201e11120777bcd1543455d1de54b89292879bcd2bbChia-I Wu if (!strcmp(createInfo.ppEnabledLayerNames[i], global_layer.layerName)) { 2025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis foundLayer = true; 2035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 2045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // This has to be logged to console as we don't have a callback at this point. 2055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!foundLayer && !strcmp(createInfo.ppEnabledLayerNames[0], "VK_LAYER_GOOGLE_unique_objects")) { 206bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski LOGCONSOLE("Cannot activate layer VK_LAYER_GOOGLE_unique_objects prior to activating %s.", global_layer.layerName); 2075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 2085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 2095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 2105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Code imported from shader_checker 2125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic void build_def_index(shader_module *); 2135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// A forward iterator over spirv instructions. Provides easy access to len, opcode, and content words 2155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// without the caller needing to care too much about the physical SPIRV module layout. 2165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstruct spirv_inst_iter { 2175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::vector<uint32_t>::const_iterator zero; 2185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::vector<uint32_t>::const_iterator it; 2195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 220b95616f79b105741b1399b01d527a8ef3b7ccfb7Chris Forbes uint32_t len() { 221b95616f79b105741b1399b01d527a8ef3b7ccfb7Chris Forbes auto result = *it >> 16; 222b95616f79b105741b1399b01d527a8ef3b7ccfb7Chris Forbes assert(result > 0); 223b95616f79b105741b1399b01d527a8ef3b7ccfb7Chris Forbes return result; 224b95616f79b105741b1399b01d527a8ef3b7ccfb7Chris Forbes } 225b95616f79b105741b1399b01d527a8ef3b7ccfb7Chris Forbes 2265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t opcode() { return *it & 0x0ffffu; } 227b95616f79b105741b1399b01d527a8ef3b7ccfb7Chris Forbes 228b95616f79b105741b1399b01d527a8ef3b7ccfb7Chris Forbes uint32_t const &word(unsigned n) { 229b95616f79b105741b1399b01d527a8ef3b7ccfb7Chris Forbes assert(n < len()); 230b95616f79b105741b1399b01d527a8ef3b7ccfb7Chris Forbes return it[n]; 231b95616f79b105741b1399b01d527a8ef3b7ccfb7Chris Forbes } 232b95616f79b105741b1399b01d527a8ef3b7ccfb7Chris Forbes 2335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t offset() { return (uint32_t)(it - zero); } 2345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis spirv_inst_iter() {} 2365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis spirv_inst_iter(std::vector<uint32_t>::const_iterator zero, std::vector<uint32_t>::const_iterator it) : zero(zero), it(it) {} 2385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool operator==(spirv_inst_iter const &other) { return it == other.it; } 2405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool operator!=(spirv_inst_iter const &other) { return it != other.it; } 2425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 243cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski spirv_inst_iter operator++(int) { // x++ 2445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis spirv_inst_iter ii = *this; 2455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis it += len(); 2465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return ii; 2475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 2485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 249cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski spirv_inst_iter operator++() { // ++x; 2505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis it += len(); 2515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return *this; 2525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 2535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 25425002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // The iterator and the value are the same thing. 2555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis spirv_inst_iter &operator*() { return *this; } 2565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis spirv_inst_iter const &operator*() const { return *this; } 2575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}; 2585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstruct shader_module { 26025002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // The spirv image itself 2615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis vector<uint32_t> words; 26225002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // A mapping of <id> to the first word of its def. this is useful because walking type 26325002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // trees, constant expressions, etc requires jumping all over the instruction stream. 2645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unordered_map<unsigned, unsigned> def_index; 265c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski bool has_valid_spirv; 2665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis shader_module(VkShaderModuleCreateInfo const *pCreateInfo) 2685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis : words((uint32_t *)pCreateInfo->pCode, (uint32_t *)pCreateInfo->pCode + pCreateInfo->codeSize / sizeof(uint32_t)), 269c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski def_index(), 270c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski has_valid_spirv(true) { 2715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis build_def_index(this); 2725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 2735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 274c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski shader_module() : has_valid_spirv(false) {} 275c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski 27625002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Expose begin() / end() to enable range-based for 277cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski spirv_inst_iter begin() const { return spirv_inst_iter(words.begin(), words.begin() + 5); } // First insn 278cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski spirv_inst_iter end() const { return spirv_inst_iter(words.begin(), words.end()); } // Just past last insn 27925002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Given an offset into the module, produce an iterator there. 2805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis spirv_inst_iter at(unsigned offset) const { return spirv_inst_iter(words.begin(), words.begin() + offset); } 2815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 28225002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Gets an iterator to the definition of an id 2835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis spirv_inst_iter get_def(unsigned id) const { 2845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto it = def_index.find(id); 2855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (it == def_index.end()) { 2865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return end(); 2875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 2885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return at(it->second); 2895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 2905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}; 2915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// TODO : This can be much smarter, using separate locks for separate global data 293b9e992386a44404152747d66817a733aa127e281Jeremy Hayesstatic std::mutex global_lock; 294593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 29579fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis// Return IMAGE_VIEW_STATE ptr for specified imageView or else NULL 2969a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisIMAGE_VIEW_STATE *GetImageViewState(const layer_data *dev_data, VkImageView image_view) { 2972c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis auto iv_it = dev_data->imageViewMap.find(image_view); 2982c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis if (iv_it == dev_data->imageViewMap.end()) { 2992c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis return nullptr; 3002c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis } 3012c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis return iv_it->second.get(); 3022c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis} 3039a55ca3674bb3fac3fbdfca9515a16a224aa9055Tobin Ehlis// Return sampler node ptr for specified sampler or else NULL 3049a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisSAMPLER_STATE *GetSamplerState(const layer_data *dev_data, VkSampler sampler) { 3052c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis auto sampler_it = dev_data->samplerMap.find(sampler); 3062c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis if (sampler_it == dev_data->samplerMap.end()) { 3079a55ca3674bb3fac3fbdfca9515a16a224aa9055Tobin Ehlis return nullptr; 3089a55ca3674bb3fac3fbdfca9515a16a224aa9055Tobin Ehlis } 3099a55ca3674bb3fac3fbdfca9515a16a224aa9055Tobin Ehlis return sampler_it->second.get(); 3109a55ca3674bb3fac3fbdfca9515a16a224aa9055Tobin Ehlis} 3115cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis// Return image state ptr for specified image or else NULL 3129a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisIMAGE_STATE *GetImageState(const layer_data *dev_data, VkImage image) { 3136d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis auto img_it = dev_data->imageMap.find(image); 3146d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis if (img_it == dev_data->imageMap.end()) { 3156d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis return nullptr; 3166d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis } 3176d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis return img_it->second.get(); 3186d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis} 3195cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis// Return buffer state ptr for specified buffer or else NULL 3209a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisBUFFER_STATE *GetBufferState(const layer_data *dev_data, VkBuffer buffer) { 3212c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis auto buff_it = dev_data->bufferMap.find(buffer); 3222c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis if (buff_it == dev_data->bufferMap.end()) { 3238718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis return nullptr; 3248718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis } 3258718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis return buff_it->second.get(); 3268718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis} 327b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis// Return swapchain node for specified swapchain or else NULL 3289a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisSWAPCHAIN_NODE *GetSwapchainNode(const layer_data *dev_data, VkSwapchainKHR swapchain) { 329b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis auto swp_it = dev_data->device_extensions.swapchainMap.find(swapchain); 330b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis if (swp_it == dev_data->device_extensions.swapchainMap.end()) { 331b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis return nullptr; 332b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis } 3333f687bf405355f3eec6bd1bc0e8d04daba37a0f9Tobin Ehlis return swp_it->second.get(); 334b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis} 335170dc65b45f6bcdec47e02b3aa19435e55b32804Tobin Ehlis// Return swapchain for specified image or else NULL 3369a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisVkSwapchainKHR GetSwapchainFromImage(const layer_data *dev_data, VkImage image) { 337170dc65b45f6bcdec47e02b3aa19435e55b32804Tobin Ehlis auto img_it = dev_data->device_extensions.imageToSwapchainMap.find(image); 338170dc65b45f6bcdec47e02b3aa19435e55b32804Tobin Ehlis if (img_it == dev_data->device_extensions.imageToSwapchainMap.end()) { 339170dc65b45f6bcdec47e02b3aa19435e55b32804Tobin Ehlis return VK_NULL_HANDLE; 340170dc65b45f6bcdec47e02b3aa19435e55b32804Tobin Ehlis } 341170dc65b45f6bcdec47e02b3aa19435e55b32804Tobin Ehlis return img_it->second; 342170dc65b45f6bcdec47e02b3aa19435e55b32804Tobin Ehlis} 3432f2db584f5d79892bd84d0a24b8ca3499985a5c2Tobin Ehlis// Return buffer node ptr for specified buffer or else NULL 3449a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisBUFFER_VIEW_STATE *GetBufferViewState(const layer_data *dev_data, VkBufferView buffer_view) { 34551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis auto bv_it = dev_data->bufferViewMap.find(buffer_view); 34651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (bv_it == dev_data->bufferViewMap.end()) { 3472f2db584f5d79892bd84d0a24b8ca3499985a5c2Tobin Ehlis return nullptr; 3482f2db584f5d79892bd84d0a24b8ca3499985a5c2Tobin Ehlis } 3492f2db584f5d79892bd84d0a24b8ca3499985a5c2Tobin Ehlis return bv_it->second.get(); 3502f2db584f5d79892bd84d0a24b8ca3499985a5c2Tobin Ehlis} 3518718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis 3529a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisFENCE_NODE *GetFenceNode(layer_data *dev_data, VkFence fence) { 35366fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes auto it = dev_data->fenceMap.find(fence); 35466fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes if (it == dev_data->fenceMap.end()) { 35566fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes return nullptr; 35666fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes } 35766fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes return &it->second; 35866fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes} 35966fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes 3609a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisEVENT_STATE *GetEventNode(layer_data *dev_data, VkEvent event) { 3619556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis auto it = dev_data->eventMap.find(event); 3629556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis if (it == dev_data->eventMap.end()) { 3639556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis return nullptr; 3649556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis } 3659556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis return &it->second; 3669556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis} 3679556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis 3689a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisQUERY_POOL_NODE *GetQueryPoolNode(layer_data *dev_data, VkQueryPool query_pool) { 369ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis auto it = dev_data->queryPoolMap.find(query_pool); 370ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis if (it == dev_data->queryPoolMap.end()) { 371ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis return nullptr; 372ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis } 373ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis return &it->second; 374ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis} 375ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis 3769a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisQUEUE_STATE *GetQueueState(layer_data *dev_data, VkQueue queue) { 37766fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes auto it = dev_data->queueMap.find(queue); 37866fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes if (it == dev_data->queueMap.end()) { 37966fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes return nullptr; 38066fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes } 38166fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes return &it->second; 38266fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes} 38366fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes 3849a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisSEMAPHORE_NODE *GetSemaphoreNode(layer_data *dev_data, VkSemaphore semaphore) { 3855e92f3cfdca6a52a3dcefd053c41f728bd036cebChris Forbes auto it = dev_data->semaphoreMap.find(semaphore); 3865e92f3cfdca6a52a3dcefd053c41f728bd036cebChris Forbes if (it == dev_data->semaphoreMap.end()) { 3875e92f3cfdca6a52a3dcefd053c41f728bd036cebChris Forbes return nullptr; 3885e92f3cfdca6a52a3dcefd053c41f728bd036cebChris Forbes } 3895e92f3cfdca6a52a3dcefd053c41f728bd036cebChris Forbes return &it->second; 3905e92f3cfdca6a52a3dcefd053c41f728bd036cebChris Forbes} 3915e92f3cfdca6a52a3dcefd053c41f728bd036cebChris Forbes 3929a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisCOMMAND_POOL_NODE *GetCommandPoolNode(layer_data *dev_data, VkCommandPool pool) { 3938d6a38de0389036581ada119e548180c614fe0efChris Forbes auto it = dev_data->commandPoolMap.find(pool); 3948d6a38de0389036581ada119e548180c614fe0efChris Forbes if (it == dev_data->commandPoolMap.end()) { 3958d6a38de0389036581ada119e548180c614fe0efChris Forbes return nullptr; 3968d6a38de0389036581ada119e548180c614fe0efChris Forbes } 3978d6a38de0389036581ada119e548180c614fe0efChris Forbes return &it->second; 3988d6a38de0389036581ada119e548180c614fe0efChris Forbes} 3993bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes 4009a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisPHYSICAL_DEVICE_STATE *GetPhysicalDeviceState(instance_layer_data *instance_data, VkPhysicalDevice phys) { 401f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbes auto it = instance_data->physical_device_map.find(phys); 402f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbes if (it == instance_data->physical_device_map.end()) { 4033bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes return nullptr; 4043bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes } 4053bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes return &it->second; 4063bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes} 4073bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes 4089a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisSURFACE_STATE *GetSurfaceState(instance_layer_data *instance_data, VkSurfaceKHR surface) { 409747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes auto it = instance_data->surface_map.find(surface); 410747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (it == instance_data->surface_map.end()) { 411747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes return nullptr; 412747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes } 413747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes return &it->second; 414747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 415747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 416f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis// Return ptr to memory binding for given handle of specified type 41751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic BINDABLE *GetObjectMemBinding(layer_data *dev_data, uint64_t handle, VkDebugReportObjectTypeEXT type) { 4185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis switch (type) { 419cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT: 4209a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis return GetImageState(dev_data, VkImage(handle)); 421cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT: 4229a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis return GetBufferState(dev_data, VkBuffer(handle)); 423cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 424cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 4255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 42694c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis return nullptr; 4275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 42872d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis// prototype 4299a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisGLOBAL_CB_NODE *GetCBNode(layer_data const *, const VkCommandBuffer); 43072d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis 4315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Return ptr to info in map container containing mem, or NULL if not found 4325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Calls to this function should be wrapped in mutex 4339a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisDEVICE_MEM_INFO *GetMemObjInfo(const layer_data *dev_data, const VkDeviceMemory mem) { 43457fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis auto mem_it = dev_data->memObjMap.find(mem); 43557fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis if (mem_it == dev_data->memObjMap.end()) { 4365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return NULL; 4375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 43857fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis return mem_it->second.get(); 4395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 4405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 44151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic void add_mem_obj_info(layer_data *dev_data, void *object, const VkDeviceMemory mem, 4425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkMemoryAllocateInfo *pAllocateInfo) { 4435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(object != NULL); 4445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 44551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->memObjMap[mem] = unique_ptr<DEVICE_MEM_INFO>(new DEVICE_MEM_INFO(object, mem, pAllocateInfo)); 4465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 447dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis 448dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis// Helper function to print lowercase string of object type 449dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis// TODO: Unify string helper functions, this should really come out of a string helper if not there already 450dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlisstatic const char *object_type_to_string(VkDebugReportObjectTypeEXT type) { 451dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis switch (type) { 452cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT: 453cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "image"; 454cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT: 455cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "buffer"; 456cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT: 457cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "image view"; 458cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT: 459cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "buffer view"; 460cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT: 461cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "swapchain"; 462cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT: 463cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "descriptor set"; 464cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT: 465cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "framebuffer"; 466cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT: 467cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "event"; 468cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT: 469cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "query pool"; 470cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT: 471cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "descriptor pool"; 472cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT: 473cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "command pool"; 474cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT: 475cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "pipeline"; 476cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT: 477cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "sampler"; 478cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT: 479cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "renderpass"; 480cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT: 481cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "device memory"; 482cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT: 483cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "semaphore"; 484cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 485cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "unknown"; 486dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis } 487dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis} 488dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis 489cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis// For given bound_object_handle, bound to given mem allocation, verify that the range for the bound object is valid 490f989de4217bce0f293121d0da53dc8328276370fTobin Ehlisstatic bool ValidateMemoryIsValid(layer_data *dev_data, VkDeviceMemory mem, uint64_t bound_object_handle, 491dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis VkDebugReportObjectTypeEXT type, const char *functionName) { 4929a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *mem_info = GetMemObjInfo(dev_data, mem); 493f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis if (mem_info) { 494f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis if (!mem_info->bound_ranges[bound_object_handle].valid) { 495f48a83f5b5548cd46a12770c7542ff902537ad3eKarl Schultz return log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 496ea8e85ade623a09c601d939622cbd7740d8d66c9Tobin Ehlis reinterpret_cast<uint64_t &>(mem), __LINE__, MEMTRACK_INVALID_MEM_REGION, "MEM", 497dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis "%s: Cannot read invalid region of memory allocation 0x%" PRIx64 " for bound %s object 0x%" PRIx64 498dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis ", please fill the memory before using.", 499dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis functionName, reinterpret_cast<uint64_t &>(mem), object_type_to_string(type), bound_object_handle); 500f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis } 501f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis } 502f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis return false; 503f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis} 5041facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis// For given image_state 5051facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis// If mem is special swapchain key, then verify that image_state valid member is true 506f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis// Else verify that the image's bound memory range is valid 50760568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinskibool ValidateImageMemoryIsValid(layer_data *dev_data, IMAGE_STATE *image_state, const char *functionName) { 508e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis if (image_state->binding.mem == MEMTRACKER_SWAP_CHAIN_IMAGE_KEY) { 5091facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis if (!image_state->valid) { 510f48a83f5b5548cd46a12770c7542ff902537ad3eKarl Schultz return log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 511e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis reinterpret_cast<uint64_t &>(image_state->binding.mem), __LINE__, MEMTRACK_INVALID_MEM_REGION, "MEM", 512414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller "%s: Cannot read invalid swapchain image 0x%" PRIx64 ", please fill the memory before using.", 5131facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis functionName, reinterpret_cast<uint64_t &>(image_state->image)); 5145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 516e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis return ValidateMemoryIsValid(dev_data, image_state->binding.mem, reinterpret_cast<uint64_t &>(image_state->image), 517dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, functionName); 5185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 5205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 5215cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis// For given buffer_state, verify that the range it's bound to is valid 522c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinskibool ValidateBufferMemoryIsValid(layer_data *dev_data, BUFFER_STATE *buffer_state, const char *functionName) { 5235cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis return ValidateMemoryIsValid(dev_data, buffer_state->binding.mem, reinterpret_cast<uint64_t &>(buffer_state->buffer), 524dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, functionName); 525f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis} 526f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis// For the given memory allocation, set the range bound by the given handle object to the valid param value 527f989de4217bce0f293121d0da53dc8328276370fTobin Ehlisstatic void SetMemoryValid(layer_data *dev_data, VkDeviceMemory mem, uint64_t handle, bool valid) { 5289a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *mem_info = GetMemObjInfo(dev_data, mem); 529f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis if (mem_info) { 530f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis mem_info->bound_ranges[handle].valid = valid; 531f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis } 532f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis} 533f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis// For given image node 5341facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis// If mem is special swapchain key, then set entire image_state to valid param value 535f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis// Else set the image's bound memory range to valid param value 536623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinskivoid SetImageMemoryValid(layer_data *dev_data, IMAGE_STATE *image_state, bool valid) { 537e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis if (image_state->binding.mem == MEMTRACKER_SWAP_CHAIN_IMAGE_KEY) { 5381facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis image_state->valid = valid; 5395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 540e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis SetMemoryValid(dev_data, image_state->binding.mem, reinterpret_cast<uint64_t &>(image_state->image), valid); 5415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 543f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis// For given buffer node set the buffer's bound memory range to valid param value 544c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinskivoid SetBufferMemoryValid(layer_data *dev_data, BUFFER_STATE *buffer_state, bool valid) { 5455cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis SetMemoryValid(dev_data, buffer_state->binding.mem, reinterpret_cast<uint64_t &>(buffer_state->buffer), valid); 546f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis} 5475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Find CB Info and add mem reference to list container 5485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Find Mem Obj Info and add CB reference to list container 549e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool update_cmd_buf_and_mem_references(layer_data *dev_data, const VkCommandBuffer cb, const VkDeviceMemory mem, 550e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves const char *apiName) { 55183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 5525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Skip validation if this image was created through WSI 5545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (mem != MEMTRACKER_SWAP_CHAIN_IMAGE_KEY) { 5555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // First update CB binding in MemObj mini CB list 5569a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *pMemInfo = GetMemObjInfo(dev_data, mem); 5575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pMemInfo) { 5585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Now update CBInfo's Mem reference list 5599a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *cb_node = GetCBNode(dev_data, cb); 560d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis pMemInfo->cb_bindings.insert(cb_node); 5615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODO: keep track of all destroyed CBs so we know if this is a stale or simply invalid object 562d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis if (cb_node) { 563d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis cb_node->memObjs.insert(mem); 5645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 56783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis return skip_call; 5685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 569ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis 57056f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis// Create binding link between given sampler and command buffer node 571d31a44af6da568692a73201825459689c9431867Tobin Ehlisvoid AddCommandBufferBindingSampler(GLOBAL_CB_NODE *cb_node, SAMPLER_STATE *sampler_state) { 572d31a44af6da568692a73201825459689c9431867Tobin Ehlis sampler_state->cb_bindings.insert(cb_node); 573d31a44af6da568692a73201825459689c9431867Tobin Ehlis cb_node->object_bindings.insert( 574d31a44af6da568692a73201825459689c9431867Tobin Ehlis {reinterpret_cast<uint64_t &>(sampler_state->sampler), VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT}); 57556f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis} 57656f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis 57756f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis// Create binding link between given image node and command buffer node 5781facd2c91911508b9fb61f54a56269841299f663Tobin Ehlisvoid AddCommandBufferBindingImage(const layer_data *dev_data, GLOBAL_CB_NODE *cb_node, IMAGE_STATE *image_state) { 579ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis // Skip validation if this image was created through WSI 580e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis if (image_state->binding.mem != MEMTRACKER_SWAP_CHAIN_IMAGE_KEY) { 581ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis // First update CB binding in MemObj mini CB list 582d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis for (auto mem_binding : image_state->GetBoundMemory()) { 5839a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *pMemInfo = GetMemObjInfo(dev_data, mem_binding); 584d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis if (pMemInfo) { 585d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis pMemInfo->cb_bindings.insert(cb_node); 586d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis // Now update CBInfo's Mem reference list 587d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis cb_node->memObjs.insert(mem_binding); 588d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis } 589ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } 590f940225c9e5e3e14b3f5a32d3ea360b585614600Tobin Ehlis // Now update cb binding for image 5911facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis cb_node->object_bindings.insert({reinterpret_cast<uint64_t &>(image_state->image), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT}); 5921facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis image_state->cb_bindings.insert(cb_node); 593ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } 594ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis} 595ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis 59603ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis// Create binding link between given image view node and its image with command buffer node 59703ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlisvoid AddCommandBufferBindingImageView(const layer_data *dev_data, GLOBAL_CB_NODE *cb_node, IMAGE_VIEW_STATE *view_state) { 59803ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis // First add bindings for imageView 59903ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis view_state->cb_bindings.insert(cb_node); 60003ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis cb_node->object_bindings.insert( 60103ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis {reinterpret_cast<uint64_t &>(view_state->image_view), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT}); 6029a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_state = GetImageState(dev_data, view_state->create_info.image); 60303ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis // Add bindings for image within imageView 6041facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis if (image_state) { 6051facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis AddCommandBufferBindingImage(dev_data, cb_node, image_state); 60603ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis } 60703ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis} 60803ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis 609ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis// Create binding link between given buffer node and command buffer node 6105cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlisvoid AddCommandBufferBindingBuffer(const layer_data *dev_data, GLOBAL_CB_NODE *cb_node, BUFFER_STATE *buffer_state) { 611ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis // First update CB binding in MemObj mini CB list 6125cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis for (auto mem_binding : buffer_state->GetBoundMemory()) { 6139a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *pMemInfo = GetMemObjInfo(dev_data, mem_binding); 614d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis if (pMemInfo) { 615d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis pMemInfo->cb_bindings.insert(cb_node); 616d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis // Now update CBInfo's Mem reference list 617d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis cb_node->memObjs.insert(mem_binding); 618d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis } 619ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } 620ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis // Now update cb binding for buffer 6215cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis cb_node->object_bindings.insert({reinterpret_cast<uint64_t &>(buffer_state->buffer), VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT}); 6225cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis buffer_state->cb_bindings.insert(cb_node); 623ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis} 624ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis 62577b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis// Create binding link between given buffer view node and its buffer with command buffer node 62677b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlisvoid AddCommandBufferBindingBufferView(const layer_data *dev_data, GLOBAL_CB_NODE *cb_node, BUFFER_VIEW_STATE *view_state) { 62777b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis // First add bindings for bufferView 62877b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis view_state->cb_bindings.insert(cb_node); 62977b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis cb_node->object_bindings.insert( 63077b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis {reinterpret_cast<uint64_t &>(view_state->buffer_view), VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT}); 6319a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto buffer_state = GetBufferState(dev_data, view_state->create_info.buffer); 63277b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis // Add bindings for buffer within bufferView 6335cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis if (buffer_state) { 6345cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis AddCommandBufferBindingBuffer(dev_data, cb_node, buffer_state); 63577b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis } 63677b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis} 63777b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis 638400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis// For every mem obj bound to particular CB, free bindings related to that CB 639d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlisstatic void clear_cmd_buf_and_mem_references(layer_data *dev_data, GLOBAL_CB_NODE *cb_node) { 640d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis if (cb_node) { 641d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis if (cb_node->memObjs.size() > 0) { 642d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis for (auto mem : cb_node->memObjs) { 6439a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *pInfo = GetMemObjInfo(dev_data, mem); 6445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pInfo) { 645d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis pInfo->cb_bindings.erase(cb_node); 6465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 648d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis cb_node->memObjs.clear(); 6495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 650d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis cb_node->validate_functions.clear(); 6515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 653400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis// Overloaded call to above function when GLOBAL_CB_NODE has not already been looked-up 654400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlisstatic void clear_cmd_buf_and_mem_references(layer_data *dev_data, const VkCommandBuffer cb) { 6559a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis clear_cmd_buf_and_mem_references(dev_data, GetCBNode(dev_data, cb)); 6565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 6575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 658f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis// Clear a single object binding from given memory object, or report error if binding is missing 659f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlisstatic bool ClearMemoryObjectBinding(layer_data *dev_data, uint64_t handle, VkDebugReportObjectTypeEXT type, VkDeviceMemory mem) { 6609a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *mem_info = GetMemObjInfo(dev_data, mem); 661f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis // This obj is bound to a memory object. Remove the reference to this object in that memory object's list 662d4cd34fd49caa759cf01cafa5fa271401b17c3b9Jeremy Hayes if (mem_info) { 663d4cd34fd49caa759cf01cafa5fa271401b17c3b9Jeremy Hayes mem_info->obj_bindings.erase({handle, type}); 664f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis } 665f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis return false; 666f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis} 667f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis 668f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis// ClearMemoryObjectBindings clears the binding of objects to memory 669f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis// For the given object it pulls the memory bindings and makes sure that the bindings 670f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis// no longer refer to the object being cleared. This occurs when objects are destroyed. 6718c59133586421be878d393799b30044497f77727Mark Lobodzinskibool ClearMemoryObjectBindings(layer_data *dev_data, uint64_t handle, VkDebugReportObjectTypeEXT type) { 672f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis bool skip = false; 673f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis BINDABLE *mem_binding = GetObjectMemBinding(dev_data, handle, type); 674f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis if (mem_binding) { 675f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis if (!mem_binding->sparse) { 676f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis skip = ClearMemoryObjectBinding(dev_data, handle, type, mem_binding->binding.mem); 677cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else { // Sparse, clear all bindings 678bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski for (auto &sparse_mem_binding : mem_binding->sparse_bindings) { 679f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis skip |= ClearMemoryObjectBinding(dev_data, handle, type, sparse_mem_binding.mem); 6805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 683f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis return skip; 6845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 6855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 686888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis// For given mem object, verify that it is not null or UNBOUND, if it is, report error. Return skip value. 687888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlisbool VerifyBoundMemoryIsValid(const layer_data *dev_data, VkDeviceMemory mem, uint64_t handle, const char *api_name, 68835ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis const char *type_name, UNIQUE_VALIDATION_ERROR_CODE error_code) { 689888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis bool result = false; 690888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis if (VK_NULL_HANDLE == mem) { 691888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis result = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, handle, 692cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, error_code, "MEM", "%s: Vk%s object 0x%" PRIxLEAST64 693cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " used with no memory bound. Memory should be bound by calling " 694cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkBind%sMemory(). %s", 69535ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis api_name, type_name, handle, type_name, validation_error_map[error_code]); 696888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis } else if (MEMORY_UNBOUND == mem) { 697888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis result = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, handle, 698cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, error_code, "MEM", "%s: Vk%s object 0x%" PRIxLEAST64 699cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " used with no memory bound and previously bound memory was freed. " 700cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Memory must not be freed prior to this operation. %s", 70135ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis api_name, type_name, handle, validation_error_map[error_code]); 702888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis } 703888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis return result; 704888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis} 705888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis 706b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski// Check to see if memory was ever bound to this image 70735ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlisbool ValidateMemoryIsBoundToImage(const layer_data *dev_data, const IMAGE_STATE *image_state, const char *api_name, 70835ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis UNIQUE_VALIDATION_ERROR_CODE error_code) { 709b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski bool result = false; 7101facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis if (0 == (static_cast<uint32_t>(image_state->createInfo.flags) & VK_IMAGE_CREATE_SPARSE_BINDING_BIT)) { 71135ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis result = VerifyBoundMemoryIsValid(dev_data, image_state->binding.mem, 71235ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis reinterpret_cast<const uint64_t &>(image_state->image), api_name, "Image", error_code); 713b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski } 714b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski return result; 715b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski} 716b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski 717b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski// Check to see if memory was bound to this buffer 71835ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlisbool ValidateMemoryIsBoundToBuffer(const layer_data *dev_data, const BUFFER_STATE *buffer_state, const char *api_name, 71935ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis UNIQUE_VALIDATION_ERROR_CODE error_code) { 720b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski bool result = false; 7215cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis if (0 == (static_cast<uint32_t>(buffer_state->createInfo.flags) & VK_BUFFER_CREATE_SPARSE_BINDING_BIT)) { 7225cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis result = VerifyBoundMemoryIsValid(dev_data, buffer_state->binding.mem, 72335ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis reinterpret_cast<const uint64_t &>(buffer_state->buffer), api_name, "Buffer", error_code); 724b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski } 725b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski return result; 726b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski} 727b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski 728f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis// SetMemBinding is used to establish immutable, non-sparse binding between a single image/buffer object and memory object 7295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// For NULL mem case, output warning 7305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Make sure given object is in global object map 7315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// IF a previous binding existed, output validation error 7325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Otherwise, add reference from objectInfo to memoryInfo 7335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Add reference off of objInfo 7344f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes// TODO: We may need to refactor or pass in multiple valid usage statements to handle multiple valid usage conditions. 735888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlisstatic bool SetMemBinding(layer_data *dev_data, VkDeviceMemory mem, uint64_t handle, VkDebugReportObjectTypeEXT type, 736888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis const char *apiName) { 73783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 738f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis // It's an error to bind an object to NULL memory 739d3876b4ff7c293a14f73fe3622513d1fa91bf2d0Jeremy Hayes if (mem != VK_NULL_HANDLE) { 740f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis BINDABLE *mem_binding = GetObjectMemBinding(dev_data, handle, type); 741888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis assert(mem_binding); 74210ffe2d353eaff714ed92a2835af77d8b5042d31Cort if (mem_binding->sparse) { 74310ffe2d353eaff714ed92a2835af77d8b5042d31Cort UNIQUE_VALIDATION_ERROR_CODE error_code = VALIDATION_ERROR_00804; 74410ffe2d353eaff714ed92a2835af77d8b5042d31Cort const char *handle_type = "IMAGE"; 74510ffe2d353eaff714ed92a2835af77d8b5042d31Cort if (strcmp(apiName, "vkBindBufferMemory") == 0) { 74610ffe2d353eaff714ed92a2835af77d8b5042d31Cort error_code = VALIDATION_ERROR_00792; 74710ffe2d353eaff714ed92a2835af77d8b5042d31Cort handle_type = "BUFFER"; 74810ffe2d353eaff714ed92a2835af77d8b5042d31Cort } else { 74910ffe2d353eaff714ed92a2835af77d8b5042d31Cort assert(strcmp(apiName, "vkBindImageMemory") == 0); 75010ffe2d353eaff714ed92a2835af77d8b5042d31Cort } 75110ffe2d353eaff714ed92a2835af77d8b5042d31Cort skip_call |= 75210ffe2d353eaff714ed92a2835af77d8b5042d31Cort log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 75310ffe2d353eaff714ed92a2835af77d8b5042d31Cort reinterpret_cast<uint64_t &>(mem), __LINE__, error_code, "MEM", 75410ffe2d353eaff714ed92a2835af77d8b5042d31Cort "In %s, attempting to bind memory (0x%" PRIxLEAST64 ") to object (0x%" PRIxLEAST64 75510ffe2d353eaff714ed92a2835af77d8b5042d31Cort ") which was created with sparse memory flags (VK_%s_CREATE_SPARSE_*_BIT). %s", 75610ffe2d353eaff714ed92a2835af77d8b5042d31Cort apiName, reinterpret_cast<uint64_t &>(mem), handle, handle_type, validation_error_map[error_code]); 75710ffe2d353eaff714ed92a2835af77d8b5042d31Cort } 7589a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *mem_info = GetMemObjInfo(dev_data, mem); 759888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis if (mem_info) { 7609a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *prev_binding = GetMemObjInfo(dev_data, mem_binding->binding.mem); 761888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis if (prev_binding) { 76298c2a17e1a549df84f4239f619bc0955f632cb43Cort UNIQUE_VALIDATION_ERROR_CODE error_code = VALIDATION_ERROR_00803; 76398c2a17e1a549df84f4239f619bc0955f632cb43Cort if (strcmp(apiName, "vkBindBufferMemory") == 0) { 76498c2a17e1a549df84f4239f619bc0955f632cb43Cort error_code = VALIDATION_ERROR_00791; 76598c2a17e1a549df84f4239f619bc0955f632cb43Cort } else { 76698c2a17e1a549df84f4239f619bc0955f632cb43Cort assert(strcmp(apiName, "vkBindImageMemory") == 0); 76798c2a17e1a549df84f4239f619bc0955f632cb43Cort } 768888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis skip_call |= 769888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 77098c2a17e1a549df84f4239f619bc0955f632cb43Cort reinterpret_cast<uint64_t &>(mem), __LINE__, error_code, "MEM", 771888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis "In %s, attempting to bind memory (0x%" PRIxLEAST64 ") to object (0x%" PRIxLEAST64 77298c2a17e1a549df84f4239f619bc0955f632cb43Cort ") which has already been bound to mem object 0x%" PRIxLEAST64 ". %s", 77398c2a17e1a549df84f4239f619bc0955f632cb43Cort apiName, reinterpret_cast<uint64_t &>(mem), handle, reinterpret_cast<uint64_t &>(prev_binding->mem), 77498c2a17e1a549df84f4239f619bc0955f632cb43Cort validation_error_map[error_code]); 775f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis } else if (mem_binding->binding.mem == MEMORY_UNBOUND) { 776888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis skip_call |= 777888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 778888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis reinterpret_cast<uint64_t &>(mem), __LINE__, MEMTRACK_REBIND_OBJECT, "MEM", 779888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis "In %s, attempting to bind memory (0x%" PRIxLEAST64 ") to object (0x%" PRIxLEAST64 780888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis ") which was previous bound to memory that has since been freed. Memory bindings are immutable in " 781888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis "Vulkan so this attempt to bind to new memory is not allowed.", 782888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis apiName, reinterpret_cast<uint64_t &>(mem), handle); 7832e415b757c1e43fda35311aad026af8d5c96681cTobin Ehlis } else { 784888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis mem_info->obj_bindings.insert({handle, type}); 7852e415b757c1e43fda35311aad026af8d5c96681cTobin Ehlis // For image objects, make sure default memory state is correctly set 7862e415b757c1e43fda35311aad026af8d5c96681cTobin Ehlis // TODO : What's the best/correct way to handle this? 7872e415b757c1e43fda35311aad026af8d5c96681cTobin Ehlis if (VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT == type) { 7889a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto const image_state = GetImageState(dev_data, VkImage(handle)); 7891facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis if (image_state) { 7901facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis VkImageCreateInfo ici = image_state->createInfo; 7912e415b757c1e43fda35311aad026af8d5c96681cTobin Ehlis if (ici.usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) { 7922e415b757c1e43fda35311aad026af8d5c96681cTobin Ehlis // TODO:: More memory state transition stuff. 7935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 796f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis mem_binding->binding.mem = mem; 7975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 80083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis return skip_call; 8015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 8025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// For NULL mem case, clear any previous binding Else... 8045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Make sure given object is in its object map 8055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// IF a previous binding existed, update binding 8065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Add reference from objectInfo to memoryInfo 8075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Add reference off of object's binding info 8080a1ce3dfd81c9f4efbe46f5ba5ddaea70bc4aa61Chris Forbes// Return VK_TRUE if addition is successful, VK_FALSE otherwise 809f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlisstatic bool SetSparseMemBinding(layer_data *dev_data, MEM_BINDING binding, uint64_t handle, VkDebugReportObjectTypeEXT type, 810f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis const char *apiName) { 81183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = VK_FALSE; 8125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Handle NULL case separately, just clear previous binding & decrement reference 813f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis if (binding.mem == VK_NULL_HANDLE) { 814f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis // TODO : This should cause the range of the resource to be unbound according to spec 8155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 816f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis BINDABLE *mem_binding = GetObjectMemBinding(dev_data, handle, type); 817f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis assert(mem_binding); 818f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis assert(mem_binding->sparse); 8199a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *mem_info = GetMemObjInfo(dev_data, binding.mem); 820f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis if (mem_info) { 821f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis mem_info->obj_bindings.insert({handle, type}); 8222e415b757c1e43fda35311aad026af8d5c96681cTobin Ehlis // Need to set mem binding for this object 823f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis mem_binding->sparse_bindings.insert(binding); 8245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 82683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis return skip_call; 827caf05e0db4959ae196ab34b024f352d9c0326870Tobin Ehlis} 828caf05e0db4959ae196ab34b024f352d9c0326870Tobin Ehlis 8295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Return a string representation of CMD_TYPE enum 8305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic string cmdTypeToString(CMD_TYPE cmd) { 8315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis switch (cmd) { 832cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_BINDPIPELINE: 833cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_BINDPIPELINE"; 834cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_BINDPIPELINEDELTA: 835cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_BINDPIPELINEDELTA"; 836cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETVIEWPORTSTATE: 837cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_SETVIEWPORTSTATE"; 838cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETLINEWIDTHSTATE: 839cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_SETLINEWIDTHSTATE"; 840cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETDEPTHBIASSTATE: 841cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_SETDEPTHBIASSTATE"; 842cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETBLENDSTATE: 843cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_SETBLENDSTATE"; 844cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETDEPTHBOUNDSSTATE: 845cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_SETDEPTHBOUNDSSTATE"; 846cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETSTENCILREADMASKSTATE: 847cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_SETSTENCILREADMASKSTATE"; 848cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETSTENCILWRITEMASKSTATE: 849cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_SETSTENCILWRITEMASKSTATE"; 850cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETSTENCILREFERENCESTATE: 851cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_SETSTENCILREFERENCESTATE"; 852cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_BINDDESCRIPTORSETS: 853cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_BINDDESCRIPTORSETS"; 854cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_BINDINDEXBUFFER: 855cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_BINDINDEXBUFFER"; 856cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_BINDVERTEXBUFFER: 857cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_BINDVERTEXBUFFER"; 858cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_DRAW: 859cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_DRAW"; 860cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_DRAWINDEXED: 861cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_DRAWINDEXED"; 862cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_DRAWINDIRECT: 863cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_DRAWINDIRECT"; 864cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_DRAWINDEXEDINDIRECT: 865cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_DRAWINDEXEDINDIRECT"; 866cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_DISPATCH: 867cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_DISPATCH"; 868cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_DISPATCHINDIRECT: 869cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_DISPATCHINDIRECT"; 870cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_COPYBUFFER: 871cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_COPYBUFFER"; 872cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_COPYIMAGE: 873cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_COPYIMAGE"; 874cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_BLITIMAGE: 875cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_BLITIMAGE"; 876cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_COPYBUFFERTOIMAGE: 877cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_COPYBUFFERTOIMAGE"; 878cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_COPYIMAGETOBUFFER: 879cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_COPYIMAGETOBUFFER"; 880cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_CLONEIMAGEDATA: 881cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_CLONEIMAGEDATA"; 882cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_UPDATEBUFFER: 883cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_UPDATEBUFFER"; 884cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_FILLBUFFER: 885cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_FILLBUFFER"; 886cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_CLEARCOLORIMAGE: 887cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_CLEARCOLORIMAGE"; 888cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_CLEARATTACHMENTS: 889cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_CLEARCOLORATTACHMENT"; 890cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_CLEARDEPTHSTENCILIMAGE: 891cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_CLEARDEPTHSTENCILIMAGE"; 892cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_RESOLVEIMAGE: 893cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_RESOLVEIMAGE"; 894cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETEVENT: 895cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_SETEVENT"; 896cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_RESETEVENT: 897cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_RESETEVENT"; 898cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_WAITEVENTS: 899cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_WAITEVENTS"; 900cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_PIPELINEBARRIER: 901cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_PIPELINEBARRIER"; 902cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_BEGINQUERY: 903cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_BEGINQUERY"; 904cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_ENDQUERY: 905cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_ENDQUERY"; 906cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_RESETQUERYPOOL: 907cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_RESETQUERYPOOL"; 908cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_COPYQUERYPOOLRESULTS: 909cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_COPYQUERYPOOLRESULTS"; 910cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_WRITETIMESTAMP: 911cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_WRITETIMESTAMP"; 912cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_INITATOMICCOUNTERS: 913cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_INITATOMICCOUNTERS"; 914cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_LOADATOMICCOUNTERS: 915cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_LOADATOMICCOUNTERS"; 916cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SAVEATOMICCOUNTERS: 917cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_SAVEATOMICCOUNTERS"; 918cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_BEGINRENDERPASS: 919cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_BEGINRENDERPASS"; 920cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_ENDRENDERPASS: 921cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_ENDRENDERPASS"; 922cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 923cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "UNKNOWN"; 9245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 9265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// SPIRV utility functions 9285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic void build_def_index(shader_module *module) { 9295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto insn : *module) { 9305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis switch (insn.opcode()) { 931cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Types 932cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeVoid: 933cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeBool: 934cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeInt: 935cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeFloat: 936cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeVector: 937cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeMatrix: 938cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeImage: 939cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeSampler: 940cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeSampledImage: 941cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeArray: 942cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeRuntimeArray: 943cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeStruct: 944cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeOpaque: 945cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypePointer: 946cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeFunction: 947cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeEvent: 948cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeDeviceEvent: 949cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeReserveId: 950cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeQueue: 951cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypePipe: 952cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski module->def_index[insn.word(1)] = insn.offset(); 953cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 9545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 955cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Fixed constants 956cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpConstantTrue: 957cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpConstantFalse: 958cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpConstant: 959cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpConstantComposite: 960cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpConstantSampler: 961cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpConstantNull: 962cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski module->def_index[insn.word(2)] = insn.offset(); 963cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 9645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 965cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Specialization constants 966cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpSpecConstantTrue: 967cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpSpecConstantFalse: 968cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpSpecConstant: 969cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpSpecConstantComposite: 970cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpSpecConstantOp: 971cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski module->def_index[insn.word(2)] = insn.offset(); 972cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 9735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 974cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Variables 975cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpVariable: 976cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski module->def_index[insn.word(2)] = insn.offset(); 977cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 9785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 979cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Functions 980cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpFunction: 981cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski module->def_index[insn.word(2)] = insn.offset(); 982cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 9835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 984cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 985cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // We don't care about any other defs for now. 986cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 9875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 9905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic spirv_inst_iter find_entrypoint(shader_module *src, char const *name, VkShaderStageFlagBits stageBits) { 9925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto insn : *src) { 9935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.opcode() == spv::OpEntryPoint) { 9945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto entrypointName = (char const *)&insn.word(3); 9955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto entrypointStageBits = 1u << insn.word(1); 9965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!strcmp(entrypointName, name) && (entrypointStageBits & stageBits)) { 9985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return insn; 9995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 10005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 10015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 10025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return src->end(); 10045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 10055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic char const *storage_class_name(unsigned sc) { 10075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis switch (sc) { 1008cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassInput: 1009cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "input"; 1010cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassOutput: 1011cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "output"; 1012cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassUniformConstant: 1013cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "const uniform"; 1014cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassUniform: 1015cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "uniform"; 1016cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassWorkgroup: 1017cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "workgroup local"; 1018cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassCrossWorkgroup: 1019cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "workgroup global"; 1020cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassPrivate: 1021cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "private global"; 1022cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassFunction: 1023cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "function"; 1024cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassGeneric: 1025cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "generic"; 1026cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassAtomicCounter: 1027cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "atomic counter"; 1028cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassImage: 1029cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "image"; 1030cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassPushConstant: 1031cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "push constant"; 1032cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 1033cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "unknown"; 10345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 10355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 10365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 103725002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// Get the value of an integral constant 10385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisunsigned get_constant_value(shader_module const *src, unsigned id) { 10395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto value = src->get_def(id); 10405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(value != src->end()); 10415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (value.opcode() != spv::OpConstant) { 104325002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // TODO: Either ensure that the specialization transform is already performed on a module we're 104425002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // considering here, OR -- specialize on the fly now. 10455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return 1; 10465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 10475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return value.word(3); 10495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 10505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10519ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbesstatic void describe_type_inner(std::ostringstream &ss, shader_module const *src, unsigned type) { 10525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto insn = src->get_def(type); 10535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(insn != src->end()); 10545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis switch (insn.opcode()) { 1056cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeBool: 1057cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << "bool"; 1058cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1059cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeInt: 1060cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << (insn.word(3) ? 's' : 'u') << "int" << insn.word(2); 1061cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1062cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeFloat: 1063cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << "float" << insn.word(2); 1064cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1065cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeVector: 1066cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << "vec" << insn.word(3) << " of "; 1067cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski describe_type_inner(ss, src, insn.word(2)); 1068cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1069cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeMatrix: 1070cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << "mat" << insn.word(3) << " of "; 1071cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski describe_type_inner(ss, src, insn.word(2)); 1072cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1073cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeArray: 1074cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << "arr[" << get_constant_value(src, insn.word(3)) << "] of "; 1075cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski describe_type_inner(ss, src, insn.word(2)); 1076cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1077cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypePointer: 1078cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << "ptr to " << storage_class_name(insn.word(2)) << " "; 1079cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski describe_type_inner(ss, src, insn.word(3)); 1080cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1081cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeStruct: { 1082cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << "struct of ("; 1083cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski for (unsigned i = 2; i < insn.len(); i++) { 1084cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski describe_type_inner(ss, src, insn.word(i)); 1085cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (i == insn.len() - 1) { 1086cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << ")"; 1087cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else { 1088cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << ", "; 1089cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 10909ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes } 1091cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 10925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 1093cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeSampler: 1094cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << "sampler"; 1095cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1096cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeSampledImage: 1097cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << "sampler+"; 1098cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski describe_type_inner(ss, src, insn.word(2)); 1099cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1100cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeImage: 1101cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << "image(dim=" << insn.word(3) << ", sampled=" << insn.word(7) << ")"; 1102cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1103cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 1104cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << "oddtype"; 1105cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 11065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 11075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 11085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 11099ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbesstatic std::string describe_type(shader_module const *src, unsigned type) { 11109ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes std::ostringstream ss; 11119ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes describe_type_inner(ss, src, type); 11129ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes return ss.str(); 11139ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes} 11149ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes 1115bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic bool is_narrow_numeric_type(spirv_inst_iter type) { 1116cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (type.opcode() != spv::OpTypeInt && type.opcode() != spv::OpTypeFloat) return false; 111737576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes return type.word(2) < 64; 111837576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes} 111937576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes 1120bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic bool types_match(shader_module const *a, shader_module const *b, unsigned a_type, unsigned b_type, bool a_arrayed, 1121bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski bool b_arrayed, bool relaxed) { 112225002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Walk two type trees together, and complain about differences 11235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto a_insn = a->get_def(a_type); 11245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto b_insn = b->get_def(b_type); 11255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(a_insn != a->end()); 11265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(b_insn != b->end()); 11275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 11287c755c8aca6857046df9516d8336416165969cb9Chris Forbes if (a_arrayed && a_insn.opcode() == spv::OpTypeArray) { 112937576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes return types_match(a, b, a_insn.word(2), b_type, false, b_arrayed, relaxed); 11307c755c8aca6857046df9516d8336416165969cb9Chris Forbes } 11317c755c8aca6857046df9516d8336416165969cb9Chris Forbes 11325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (b_arrayed && b_insn.opcode() == spv::OpTypeArray) { 113325002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // We probably just found the extra level of arrayness in b_type: compare the type inside it to a_type 113437576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes return types_match(a, b, a_type, b_insn.word(2), a_arrayed, false, relaxed); 113537576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes } 113637576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes 113737576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes if (a_insn.opcode() == spv::OpTypeVector && relaxed && is_narrow_numeric_type(b_insn)) { 113837576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes return types_match(a, b, a_insn.word(2), b_type, a_arrayed, b_arrayed, false); 11395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 11405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 11415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (a_insn.opcode() != b_insn.opcode()) { 11425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 11435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 11445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 11457c755c8aca6857046df9516d8336416165969cb9Chris Forbes if (a_insn.opcode() == spv::OpTypePointer) { 114625002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Match on pointee type. storage class is expected to differ 114737576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes return types_match(a, b, a_insn.word(3), b_insn.word(3), a_arrayed, b_arrayed, relaxed); 11487c755c8aca6857046df9516d8336416165969cb9Chris Forbes } 11497c755c8aca6857046df9516d8336416165969cb9Chris Forbes 11507c755c8aca6857046df9516d8336416165969cb9Chris Forbes if (a_arrayed || b_arrayed) { 115125002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // If we havent resolved array-of-verts by here, we're not going to. 11527c755c8aca6857046df9516d8336416165969cb9Chris Forbes return false; 11537c755c8aca6857046df9516d8336416165969cb9Chris Forbes } 11547c755c8aca6857046df9516d8336416165969cb9Chris Forbes 11555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis switch (a_insn.opcode()) { 1156cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeBool: 1157cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return true; 1158cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeInt: 1159cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Match on width, signedness 1160cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return a_insn.word(2) == b_insn.word(2) && a_insn.word(3) == b_insn.word(3); 1161cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeFloat: 1162cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Match on width 1163cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return a_insn.word(2) == b_insn.word(2); 1164cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeVector: 1165cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Match on element type, count. 1166cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!types_match(a, b, a_insn.word(2), b_insn.word(2), a_arrayed, b_arrayed, false)) return false; 1167cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (relaxed && is_narrow_numeric_type(a->get_def(a_insn.word(2)))) { 1168cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return a_insn.word(3) >= b_insn.word(3); 1169cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else { 1170cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return a_insn.word(3) == b_insn.word(3); 11715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 1172cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeMatrix: 1173cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Match on element type, count. 1174cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return types_match(a, b, a_insn.word(2), b_insn.word(2), a_arrayed, b_arrayed, false) && 1175cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski a_insn.word(3) == b_insn.word(3); 1176cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeArray: 1177cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Match on element type, count. these all have the same layout. we don't get here if b_arrayed. This differs from 1178cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // vector & matrix types in that the array size is the id of a constant instruction, * not a literal within OpTypeArray 1179cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return types_match(a, b, a_insn.word(2), b_insn.word(2), a_arrayed, b_arrayed, false) && 1180cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski get_constant_value(a, a_insn.word(3)) == get_constant_value(b, b_insn.word(3)); 1181cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeStruct: 1182cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Match on all element types 1183cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski { 1184cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (a_insn.len() != b_insn.len()) { 1185cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return false; // Structs cannot match if member counts differ 1186cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 11875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1188cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski for (unsigned i = 2; i < a_insn.len(); i++) { 1189cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!types_match(a, b, a_insn.word(i), b_insn.word(i), a_arrayed, b_arrayed, false)) { 1190cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return false; 1191cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 1192cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 1193cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski 1194cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return true; 1195cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 1196cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 1197cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Remaining types are CLisms, or may not appear in the interfaces we are interested in. Just claim no match. 1198cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return false; 11995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 12005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 12015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 12025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic int value_or_default(std::unordered_map<unsigned, unsigned> const &map, unsigned id, int def) { 12035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto it = map.find(id); 12045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (it == map.end()) 12055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return def; 12065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis else 12075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return it->second; 12085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 12095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 12105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic unsigned get_locations_consumed_by_type(shader_module const *src, unsigned type, bool strip_array_level) { 12115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto insn = src->get_def(type); 12125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(insn != src->end()); 12135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 12145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis switch (insn.opcode()) { 1215cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypePointer: 1216cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // See through the ptr -- this is only ever at the toplevel for graphics shaders we're never actually passing 1217cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // pointers around. 1218cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return get_locations_consumed_by_type(src, insn.word(3), strip_array_level); 1219cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeArray: 1220cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (strip_array_level) { 1221cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return get_locations_consumed_by_type(src, insn.word(2), false); 1222cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else { 1223cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return get_constant_value(src, insn.word(3)) * get_locations_consumed_by_type(src, insn.word(2), false); 1224cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 1225cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeMatrix: 1226cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Num locations is the dimension * element size 1227cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return insn.word(3) * get_locations_consumed_by_type(src, insn.word(2), false); 1228cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeVector: { 1229cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski auto scalar_type = src->get_def(insn.word(2)); 1230cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski auto bit_width = 1231cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski (scalar_type.opcode() == spv::OpTypeInt || scalar_type.opcode() == spv::OpTypeFloat) ? scalar_type.word(2) : 32; 1232cc52143fc093e1e62d2dacc4abc3966e04b6f6d6Chris Forbes 1233cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Locations are 128-bit wide; 3- and 4-component vectors of 64 bit types require two. 1234cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return (bit_width * insn.word(3) + 127) / 128; 1235cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 1236cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 1237cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Everything else is just 1. 1238cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return 1; 12395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1240cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // TODO: extend to handle 64bit scalar types, whose vectors may need multiple locations. 12415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 12425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 12435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1244c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbesstatic unsigned get_locations_consumed_by_format(VkFormat format) { 1245c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes switch (format) { 1246cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64G64B64A64_SFLOAT: 1247cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64G64B64A64_SINT: 1248cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64G64B64A64_UINT: 1249cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64G64B64_SFLOAT: 1250cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64G64B64_SINT: 1251cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64G64B64_UINT: 1252cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return 2; 1253cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 1254cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return 1; 1255c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes } 1256c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes} 1257c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes 12585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlistypedef std::pair<unsigned, unsigned> location_t; 12595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlistypedef std::pair<unsigned, unsigned> descriptor_slot_t; 12605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 12615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstruct interface_var { 12625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t id; 12635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t type_id; 12645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t offset; 1265b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes bool is_patch; 1266fff9393206f66a154438e16fa0562c989f425498Chris Forbes bool is_block_member; 1267b0436668e6594b8528e96de7bed208399fb2431dChris Forbes bool is_relaxed_precision; 126825002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // TODO: collect the name, too? Isn't required to be present. 12695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}; 12705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1271031261d21af8907953dd763398ce9a23e65b8749Chris Forbesstruct shader_stage_attributes { 1272031261d21af8907953dd763398ce9a23e65b8749Chris Forbes char const *const name; 1273031261d21af8907953dd763398ce9a23e65b8749Chris Forbes bool arrayed_input; 1274031261d21af8907953dd763398ce9a23e65b8749Chris Forbes bool arrayed_output; 1275031261d21af8907953dd763398ce9a23e65b8749Chris Forbes}; 1276031261d21af8907953dd763398ce9a23e65b8749Chris Forbes 1277031261d21af8907953dd763398ce9a23e65b8749Chris Forbesstatic shader_stage_attributes shader_stage_attribs[] = { 1278bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vertex shader", false, false}, {"tessellation control shader", true, true}, {"tessellation evaluation shader", true, false}, 1279bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"geometry shader", true, false}, {"fragment shader", false, false}, 1280031261d21af8907953dd763398ce9a23e65b8749Chris Forbes}; 1281031261d21af8907953dd763398ce9a23e65b8749Chris Forbes 12825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic spirv_inst_iter get_struct_type(shader_module const *src, spirv_inst_iter def, bool is_array_of_verts) { 12835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis while (true) { 12845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (def.opcode() == spv::OpTypePointer) { 12855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis def = src->get_def(def.word(3)); 12865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (def.opcode() == spv::OpTypeArray && is_array_of_verts) { 12875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis def = src->get_def(def.word(2)); 12885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis is_array_of_verts = false; 12895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (def.opcode() == spv::OpTypeStruct) { 12905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return def; 12915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 12925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return src->end(); 12935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 12945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 12955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 12965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1297bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic void collect_interface_block_members(shader_module const *src, std::map<location_t, interface_var> *out, 12985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_map<unsigned, unsigned> const &blocks, bool is_array_of_verts, 1299b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes uint32_t id, uint32_t type_id, bool is_patch) { 130025002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Walk down the type_id presented, trying to determine whether it's actually an interface block. 1301031261d21af8907953dd763398ce9a23e65b8749Chris Forbes auto type = get_struct_type(src, src->get_def(type_id), is_array_of_verts && !is_patch); 13025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (type == src->end() || blocks.find(type.word(1)) == blocks.end()) { 130325002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // This isn't an interface block. 13045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return; 13055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 13075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_map<unsigned, unsigned> member_components; 13085b9f2047984d6ca10d89a35ba8a2ebe0fa6bff69Chris Forbes std::unordered_map<unsigned, unsigned> member_relaxed_precision; 13095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 131025002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Walk all the OpMemberDecorate for type's result id -- first pass, collect components. 13115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto insn : *src) { 13125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.opcode() == spv::OpMemberDecorate && insn.word(1) == type.word(1)) { 13135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned member_index = insn.word(2); 13145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 13155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.word(3) == spv::DecorationComponent) { 13165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned component = insn.word(4); 13175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis member_components[member_index] = component; 13185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13195b9f2047984d6ca10d89a35ba8a2ebe0fa6bff69Chris Forbes 13205b9f2047984d6ca10d89a35ba8a2ebe0fa6bff69Chris Forbes if (insn.word(3) == spv::DecorationRelaxedPrecision) { 13215b9f2047984d6ca10d89a35ba8a2ebe0fa6bff69Chris Forbes member_relaxed_precision[member_index] = 1; 13225b9f2047984d6ca10d89a35ba8a2ebe0fa6bff69Chris Forbes } 13235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 132625002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Second pass -- produce the output, from Location decorations 13275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto insn : *src) { 13285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.opcode() == spv::OpMemberDecorate && insn.word(1) == type.word(1)) { 13295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned member_index = insn.word(2); 13305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned member_type_id = type.word(2 + member_index); 13315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 13325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.word(3) == spv::DecorationLocation) { 13335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned location = insn.word(4); 13345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned num_locations = get_locations_consumed_by_type(src, member_type_id, false); 13355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto component_it = member_components.find(member_index); 13365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned component = component_it == member_components.end() ? 0 : component_it->second; 13375b9f2047984d6ca10d89a35ba8a2ebe0fa6bff69Chris Forbes bool is_relaxed_precision = member_relaxed_precision.find(member_index) != member_relaxed_precision.end(); 13385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 13395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (unsigned int offset = 0; offset < num_locations; offset++) { 1340b0436668e6594b8528e96de7bed208399fb2431dChris Forbes interface_var v = {}; 13415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis v.id = id; 134225002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // TODO: member index in interface_var too? 13435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis v.type_id = member_type_id; 13445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis v.offset = offset; 1345b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes v.is_patch = is_patch; 1346fff9393206f66a154438e16fa0562c989f425498Chris Forbes v.is_block_member = true; 13475b9f2047984d6ca10d89a35ba8a2ebe0fa6bff69Chris Forbes v.is_relaxed_precision = is_relaxed_precision; 13483a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes (*out)[std::make_pair(location + offset, component)] = v; 13495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 13545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1355bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic std::map<location_t, interface_var> collect_interface_by_location(shader_module const *src, spirv_inst_iter entrypoint, 1356bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski spv::StorageClass sinterface, bool is_array_of_verts) { 13575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_map<unsigned, unsigned> var_locations; 13585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_map<unsigned, unsigned> var_builtins; 13595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_map<unsigned, unsigned> var_components; 13605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_map<unsigned, unsigned> blocks; 1361b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes std::unordered_map<unsigned, unsigned> var_patch; 1362b0436668e6594b8528e96de7bed208399fb2431dChris Forbes std::unordered_map<unsigned, unsigned> var_relaxed_precision; 13635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 13645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto insn : *src) { 136525002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // We consider two interface models: SSO rendezvous-by-location, and builtins. Complain about anything that 136625002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // fits neither model. 13675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.opcode() == spv::OpDecorate) { 13685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.word(2) == spv::DecorationLocation) { 13695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis var_locations[insn.word(1)] = insn.word(3); 13705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 13725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.word(2) == spv::DecorationBuiltIn) { 13735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis var_builtins[insn.word(1)] = insn.word(3); 13745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 13765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.word(2) == spv::DecorationComponent) { 13775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis var_components[insn.word(1)] = insn.word(3); 13785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 13805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.word(2) == spv::DecorationBlock) { 13815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis blocks[insn.word(1)] = 1; 13825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 1383b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes 1384b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes if (insn.word(2) == spv::DecorationPatch) { 1385b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes var_patch[insn.word(1)] = 1; 1386b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes } 1387b0436668e6594b8528e96de7bed208399fb2431dChris Forbes 1388b0436668e6594b8528e96de7bed208399fb2431dChris Forbes if (insn.word(2) == spv::DecorationRelaxedPrecision) { 1389b0436668e6594b8528e96de7bed208399fb2431dChris Forbes var_relaxed_precision[insn.word(1)] = 1; 1390b0436668e6594b8528e96de7bed208399fb2431dChris Forbes } 13915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 139425002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // TODO: handle grouped decorations 139525002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // TODO: handle index=1 dual source outputs from FS -- two vars will have the same location, and we DON'T want to clobber. 13965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 139725002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Find the end of the entrypoint's name string. additional zero bytes follow the actual null terminator, to fill out the 139825002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // rest of the word - so we only need to look at the last byte in the word to determine which word contains the terminator. 1399c15b801a6e1a5dd5eed09e689aecdde7c4a90a5bMichael Mc Donnell uint32_t word = 3; 14005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis while (entrypoint.word(word) & 0xff000000u) { 14015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis ++word; 14025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 14035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis ++word; 14045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 14053a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes std::map<location_t, interface_var> out; 14063a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes 14075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (; word < entrypoint.len(); word++) { 14085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto insn = src->get_def(entrypoint.word(word)); 14095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(insn != src->end()); 14105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(insn.opcode() == spv::OpVariable); 14115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 14121d5109d5e0dcc530b27e632e73e1be5e12a28dcdJamie Madill if (insn.word(3) == static_cast<uint32_t>(sinterface)) { 14135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned id = insn.word(2); 14145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned type = insn.word(1); 14155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 14165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis int location = value_or_default(var_locations, id, -1); 14175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis int builtin = value_or_default(var_builtins, id, -1); 1418cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski unsigned component = value_or_default(var_components, id, 0); // Unspecified is OK, is 0 1419b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes bool is_patch = var_patch.find(id) != var_patch.end(); 1420b0436668e6594b8528e96de7bed208399fb2431dChris Forbes bool is_relaxed_precision = var_relaxed_precision.find(id) != var_relaxed_precision.end(); 14215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 142225002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // All variables and interface block members in the Input or Output storage classes must be decorated with either 142325002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // a builtin or an explicit location. 142425002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // 142525002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // TODO: integrate the interface block support here. For now, don't complain -- a valid SPIRV module will only hit 142625002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // this path for the interface block case, as the individual members of the type are decorated, rather than 142725002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // variable declarations. 14285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 14295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (location != -1) { 143025002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // A user-defined interface variable, with a location. Where a variable occupied multiple locations, emit 143125002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // one result for each. 14327c755c8aca6857046df9516d8336416165969cb9Chris Forbes unsigned num_locations = get_locations_consumed_by_type(src, type, is_array_of_verts && !is_patch); 14335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (unsigned int offset = 0; offset < num_locations; offset++) { 1434b0436668e6594b8528e96de7bed208399fb2431dChris Forbes interface_var v = {}; 14355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis v.id = id; 14365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis v.type_id = type; 14375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis v.offset = offset; 1438b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes v.is_patch = is_patch; 1439b0436668e6594b8528e96de7bed208399fb2431dChris Forbes v.is_relaxed_precision = is_relaxed_precision; 14405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis out[std::make_pair(location + offset, component)] = v; 14415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 14425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (builtin == -1) { 144325002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // An interface block instance 14443a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes collect_interface_block_members(src, &out, blocks, is_array_of_verts, id, type, is_patch); 14455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 14465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 14475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 14483a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes 14493a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes return out; 14505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 14515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1452cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskistatic std::vector<std::pair<uint32_t, interface_var>> collect_interface_by_input_attachment_index( 1453cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski debug_report_data *report_data, shader_module const *src, std::unordered_set<uint32_t> const &accessible_ids) { 14543a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes std::vector<std::pair<uint32_t, interface_var>> out; 1455745d49409296f060402b57950384caadb636a2b2Chris Forbes 1456745d49409296f060402b57950384caadb636a2b2Chris Forbes for (auto insn : *src) { 1457745d49409296f060402b57950384caadb636a2b2Chris Forbes if (insn.opcode() == spv::OpDecorate) { 1458745d49409296f060402b57950384caadb636a2b2Chris Forbes if (insn.word(2) == spv::DecorationInputAttachmentIndex) { 1459745d49409296f060402b57950384caadb636a2b2Chris Forbes auto attachment_index = insn.word(3); 1460745d49409296f060402b57950384caadb636a2b2Chris Forbes auto id = insn.word(1); 1461745d49409296f060402b57950384caadb636a2b2Chris Forbes 1462745d49409296f060402b57950384caadb636a2b2Chris Forbes if (accessible_ids.count(id)) { 1463745d49409296f060402b57950384caadb636a2b2Chris Forbes auto def = src->get_def(id); 1464745d49409296f060402b57950384caadb636a2b2Chris Forbes assert(def != src->end()); 1465745d49409296f060402b57950384caadb636a2b2Chris Forbes 1466745d49409296f060402b57950384caadb636a2b2Chris Forbes if (def.opcode() == spv::OpVariable && insn.word(3) == spv::StorageClassUniformConstant) { 1467e0cc9b3441a24e4fbd2b4e0a9d163dab2140264aChris Forbes auto num_locations = get_locations_consumed_by_type(src, def.word(1), false); 1468e0cc9b3441a24e4fbd2b4e0a9d163dab2140264aChris Forbes for (unsigned int offset = 0; offset < num_locations; offset++) { 1469b0436668e6594b8528e96de7bed208399fb2431dChris Forbes interface_var v = {}; 1470e0cc9b3441a24e4fbd2b4e0a9d163dab2140264aChris Forbes v.id = id; 1471e0cc9b3441a24e4fbd2b4e0a9d163dab2140264aChris Forbes v.type_id = def.word(1); 1472e0cc9b3441a24e4fbd2b4e0a9d163dab2140264aChris Forbes v.offset = offset; 1473e0cc9b3441a24e4fbd2b4e0a9d163dab2140264aChris Forbes out.emplace_back(attachment_index + offset, v); 1474e0cc9b3441a24e4fbd2b4e0a9d163dab2140264aChris Forbes } 1475745d49409296f060402b57950384caadb636a2b2Chris Forbes } 1476745d49409296f060402b57950384caadb636a2b2Chris Forbes } 1477745d49409296f060402b57950384caadb636a2b2Chris Forbes } 1478745d49409296f060402b57950384caadb636a2b2Chris Forbes } 1479745d49409296f060402b57950384caadb636a2b2Chris Forbes } 14803a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes 14813a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes return out; 1482745d49409296f060402b57950384caadb636a2b2Chris Forbes} 1483745d49409296f060402b57950384caadb636a2b2Chris Forbes 1484cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskistatic std::vector<std::pair<descriptor_slot_t, interface_var>> collect_interface_by_descriptor_slot( 1485cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski debug_report_data *report_data, shader_module const *src, std::unordered_set<uint32_t> const &accessible_ids) { 14865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_map<unsigned, unsigned> var_sets; 14875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_map<unsigned, unsigned> var_bindings; 14885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 14895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto insn : *src) { 149025002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // All variables in the Uniform or UniformConstant storage classes are required to be decorated with both 149125002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // DecorationDescriptorSet and DecorationBinding. 14925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.opcode() == spv::OpDecorate) { 14935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.word(2) == spv::DecorationDescriptorSet) { 14945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis var_sets[insn.word(1)] = insn.word(3); 14955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 14965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 14975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.word(2) == spv::DecorationBinding) { 14985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis var_bindings[insn.word(1)] = insn.word(3); 14995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 15005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 15015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 15025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 15033a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes std::vector<std::pair<descriptor_slot_t, interface_var>> out; 15043a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes 15055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto id : accessible_ids) { 15065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto insn = src->get_def(id); 15075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(insn != src->end()); 15085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 15095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.opcode() == spv::OpVariable && 15105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (insn.word(3) == spv::StorageClassUniform || insn.word(3) == spv::StorageClassUniformConstant)) { 15115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned set = value_or_default(var_sets, insn.word(2), 0); 15125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned binding = value_or_default(var_bindings, insn.word(2), 0); 15135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1514b0436668e6594b8528e96de7bed208399fb2431dChris Forbes interface_var v = {}; 15155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis v.id = insn.word(2); 15165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis v.type_id = insn.word(1); 1517cefd4dd8e03c5dae11a05d04a03cb856190358e0Chris Forbes out.emplace_back(std::make_pair(set, binding), v); 15185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 15195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 15203a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes 15213a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes return out; 15225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 15235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1524edef66e03ed509994449d598f4fadea1a487d41bChris Forbesstatic bool validate_interface_between_stages(debug_report_data *report_data, shader_module const *producer, 1525031261d21af8907953dd763398ce9a23e65b8749Chris Forbes spirv_inst_iter producer_entrypoint, shader_stage_attributes const *producer_stage, 15265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis shader_module const *consumer, spirv_inst_iter consumer_entrypoint, 1527031261d21af8907953dd763398ce9a23e65b8749Chris Forbes shader_stage_attributes const *consumer_stage) { 15285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool pass = true; 15295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1530bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto outputs = 1531bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski collect_interface_by_location(producer, producer_entrypoint, spv::StorageClassOutput, producer_stage->arrayed_output); 1532bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto inputs = 1533bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski collect_interface_by_location(consumer, consumer_entrypoint, spv::StorageClassInput, consumer_stage->arrayed_input); 15345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 15355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto a_it = outputs.begin(); 15365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto b_it = inputs.begin(); 15375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 153825002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Maps sorted by key (location); walk them together to find mismatches 15395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis while ((outputs.size() > 0 && a_it != outputs.end()) || (inputs.size() && b_it != inputs.end())) { 15405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool a_at_end = outputs.size() == 0 || a_it == outputs.end(); 15415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool b_at_end = inputs.size() == 0 || b_it == inputs.end(); 15425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto a_first = a_at_end ? std::make_pair(0u, 0u) : a_it->first; 15435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto b_first = b_at_end ? std::make_pair(0u, 0u) : b_it->first; 15445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 15455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (b_at_end || ((!a_at_end) && (a_first < b_first))) { 1546bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 1547bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SHADER_CHECKER_OUTPUT_NOT_CONSUMED, "SC", "%s writes to output location %u.%u which is not consumed by %s", 1548bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski producer_stage->name, a_first.first, a_first.second, consumer_stage->name)) { 15495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pass = false; 15505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 15515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis a_it++; 15525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (a_at_end || a_first > b_first) { 1553bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 1554bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SHADER_CHECKER_INPUT_NOT_PRODUCED, "SC", "%s consumes input location %u.%u which is not written by %s", 1555bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski consumer_stage->name, b_first.first, b_first.second, producer_stage->name)) { 15565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pass = false; 15575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 15585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis b_it++; 15595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 1560fff9393206f66a154438e16fa0562c989f425498Chris Forbes // subtleties of arrayed interfaces: 1561fff9393206f66a154438e16fa0562c989f425498Chris Forbes // - if is_patch, then the member is not arrayed, even though the interface may be. 1562fff9393206f66a154438e16fa0562c989f425498Chris Forbes // - if is_block_member, then the extra array level of an arrayed interface is not 1563fff9393206f66a154438e16fa0562c989f425498Chris Forbes // expressed in the member type -- it's expressed in the block type. 15640f44c68c2575ba2fc83d8c8f2f5ea09548f40686Chris Forbes if (!types_match(producer, consumer, a_it->second.type_id, b_it->second.type_id, 1565fff9393206f66a154438e16fa0562c989f425498Chris Forbes producer_stage->arrayed_output && !a_it->second.is_patch && !a_it->second.is_block_member, 1566bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski consumer_stage->arrayed_input && !b_it->second.is_patch && !b_it->second.is_block_member, true)) { 1567bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 1568bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SHADER_CHECKER_INTERFACE_TYPE_MISMATCH, "SC", "Type mismatch on location %u.%u: '%s' vs '%s'", 1569bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski a_first.first, a_first.second, describe_type(producer, a_it->second.type_id).c_str(), 15709ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes describe_type(consumer, b_it->second.type_id).c_str())) { 15715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pass = false; 15725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 15735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 15740f44c68c2575ba2fc83d8c8f2f5ea09548f40686Chris Forbes if (a_it->second.is_patch != b_it->second.is_patch) { 1575bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 0, __LINE__, 1576bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SHADER_CHECKER_INTERFACE_TYPE_MISMATCH, "SC", 1577f706c50be3a9d4d1e131c2f43ee2fb443f028d30Chris Forbes "Decoration mismatch on location %u.%u: is per-%s in %s stage but " 1578bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "per-%s in %s stage", 1579bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski a_first.first, a_first.second, a_it->second.is_patch ? "patch" : "vertex", producer_stage->name, 15800f44c68c2575ba2fc83d8c8f2f5ea09548f40686Chris Forbes b_it->second.is_patch ? "patch" : "vertex", consumer_stage->name)) { 15810f44c68c2575ba2fc83d8c8f2f5ea09548f40686Chris Forbes pass = false; 15820f44c68c2575ba2fc83d8c8f2f5ea09548f40686Chris Forbes } 15830f44c68c2575ba2fc83d8c8f2f5ea09548f40686Chris Forbes } 158417c6bacf91ac671cb33212071b87b8ea782812f5Chris Forbes if (a_it->second.is_relaxed_precision != b_it->second.is_relaxed_precision) { 1585bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 0, __LINE__, 1586bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SHADER_CHECKER_INTERFACE_TYPE_MISMATCH, "SC", 1587bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "Decoration mismatch on location %u.%u: %s and %s stages differ in precision", a_first.first, 1588bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski a_first.second, producer_stage->name, consumer_stage->name)) { 158917c6bacf91ac671cb33212071b87b8ea782812f5Chris Forbes pass = false; 159017c6bacf91ac671cb33212071b87b8ea782812f5Chris Forbes } 159117c6bacf91ac671cb33212071b87b8ea782812f5Chris Forbes } 15925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis a_it++; 15935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis b_it++; 15945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 15955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 15965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 15975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return pass; 15985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 15995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 16005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisenum FORMAT_TYPE { 16015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis FORMAT_TYPE_UNDEFINED, 1602cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski FORMAT_TYPE_FLOAT, // UNORM, SNORM, FLOAT, USCALED, SSCALED, SRGB -- anything we consider float in the shader 16035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis FORMAT_TYPE_SINT, 16045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis FORMAT_TYPE_UINT, 16055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}; 16065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 16075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic unsigned get_format_type(VkFormat fmt) { 16085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis switch (fmt) { 1609cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_UNDEFINED: 1610cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return FORMAT_TYPE_UNDEFINED; 1611cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R8_SINT: 1612cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R8G8_SINT: 1613cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R8G8B8_SINT: 1614cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R8G8B8A8_SINT: 1615cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R16_SINT: 1616cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R16G16_SINT: 1617cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R16G16B16_SINT: 1618cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R16G16B16A16_SINT: 1619cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R32_SINT: 1620cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R32G32_SINT: 1621cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R32G32B32_SINT: 1622cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R32G32B32A32_SINT: 1623cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64_SINT: 1624cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64G64_SINT: 1625cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64G64B64_SINT: 1626cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64G64B64A64_SINT: 1627cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_B8G8R8_SINT: 1628cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_B8G8R8A8_SINT: 1629cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_A8B8G8R8_SINT_PACK32: 1630cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_A2B10G10R10_SINT_PACK32: 1631cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_A2R10G10B10_SINT_PACK32: 1632cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return FORMAT_TYPE_SINT; 1633cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R8_UINT: 1634cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R8G8_UINT: 1635cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R8G8B8_UINT: 1636cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R8G8B8A8_UINT: 1637cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R16_UINT: 1638cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R16G16_UINT: 1639cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R16G16B16_UINT: 1640cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R16G16B16A16_UINT: 1641cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R32_UINT: 1642cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R32G32_UINT: 1643cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R32G32B32_UINT: 1644cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R32G32B32A32_UINT: 1645cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64_UINT: 1646cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64G64_UINT: 1647cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64G64B64_UINT: 1648cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64G64B64A64_UINT: 1649cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_B8G8R8_UINT: 1650cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_B8G8R8A8_UINT: 1651cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_A8B8G8R8_UINT_PACK32: 1652cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_A2B10G10R10_UINT_PACK32: 1653cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_A2R10G10B10_UINT_PACK32: 1654cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return FORMAT_TYPE_UINT; 1655cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 1656cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return FORMAT_TYPE_FLOAT; 16575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 16585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 16595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 166025002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// characterizes a SPIR-V type appearing in an interface to a FF stage, for comparison to a VkFormat's characterization above. 16615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic unsigned get_fundamental_type(shader_module const *src, unsigned type) { 16625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto insn = src->get_def(type); 16635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(insn != src->end()); 16645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 16655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis switch (insn.opcode()) { 1666cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeInt: 1667cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return insn.word(3) ? FORMAT_TYPE_SINT : FORMAT_TYPE_UINT; 1668cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeFloat: 1669cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return FORMAT_TYPE_FLOAT; 1670cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeVector: 1671cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return get_fundamental_type(src, insn.word(2)); 1672cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeMatrix: 1673cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return get_fundamental_type(src, insn.word(2)); 1674cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeArray: 1675cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return get_fundamental_type(src, insn.word(2)); 1676cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypePointer: 1677cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return get_fundamental_type(src, insn.word(3)); 1678cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeImage: 1679cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return get_fundamental_type(src, insn.word(2)); 1680cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski 1681cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 1682cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return FORMAT_TYPE_UNDEFINED; 16835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 16845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 16855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 16865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic uint32_t get_shader_stage_id(VkShaderStageFlagBits stage) { 16875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t bit_pos = u_ffs(stage); 16885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return bit_pos - 1; 16895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 16905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1691edef66e03ed509994449d598f4fadea1a487d41bChris Forbesstatic bool validate_vi_consistency(debug_report_data *report_data, VkPipelineVertexInputStateCreateInfo const *vi) { 169225002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Walk the binding descriptions, which describe the step rate and stride of each vertex buffer. Each binding should 169325002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // be specified only once. 16945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_map<uint32_t, VkVertexInputBindingDescription const *> bindings; 16955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool pass = true; 16965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 16975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (unsigned i = 0; i < vi->vertexBindingDescriptionCount; i++) { 16985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto desc = &vi->pVertexBindingDescriptions[i]; 16995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto &binding = bindings[desc->binding]; 17005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (binding) { 17014f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes // TODO: VALIDATION_ERROR_02105 perhaps? 1702bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 1703bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SHADER_CHECKER_INCONSISTENT_VI, "SC", "Duplicate vertex input binding descriptions for binding %d", 1704bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski desc->binding)) { 17055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pass = false; 17065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 17085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis binding = desc; 17095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 17125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return pass; 17135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 17145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1715edef66e03ed509994449d598f4fadea1a487d41bChris Forbesstatic bool validate_vi_against_vs_inputs(debug_report_data *report_data, VkPipelineVertexInputStateCreateInfo const *vi, 17165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis shader_module const *vs, spirv_inst_iter entrypoint) { 17175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool pass = true; 17185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 17193a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes auto inputs = collect_interface_by_location(vs, entrypoint, spv::StorageClassInput, false); 17205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 172125002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Build index by location 17225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::map<uint32_t, VkVertexInputAttributeDescription const *> attribs; 17235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (vi) { 1724c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes for (unsigned i = 0; i < vi->vertexAttributeDescriptionCount; i++) { 1725c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes auto num_locations = get_locations_consumed_by_format(vi->pVertexAttributeDescriptions[i].format); 1726c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes for (auto j = 0u; j < num_locations; j++) { 1727c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes attribs[vi->pVertexAttributeDescriptions[i].location + j] = &vi->pVertexAttributeDescriptions[i]; 1728c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes } 1729c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes } 17305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 17325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto it_a = attribs.begin(); 17335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto it_b = inputs.begin(); 17341730e0dd28b3abc660b4e4704cf6d414f7fd4ad6Chris Forbes bool used = false; 17355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 17365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis while ((attribs.size() > 0 && it_a != attribs.end()) || (inputs.size() > 0 && it_b != inputs.end())) { 17375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool a_at_end = attribs.size() == 0 || it_a == attribs.end(); 17385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool b_at_end = inputs.size() == 0 || it_b == inputs.end(); 17395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto a_first = a_at_end ? 0 : it_a->first; 17405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto b_first = b_at_end ? 0 : it_b->first.first; 17415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!a_at_end && (b_at_end || a_first < b_first)) { 17421730e0dd28b3abc660b4e4704cf6d414f7fd4ad6Chris Forbes if (!used && log_msg(report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, 1743bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski __LINE__, SHADER_CHECKER_OUTPUT_NOT_CONSUMED, "SC", 1744bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "Vertex attribute at location %d not consumed by vertex shader", a_first)) { 17455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pass = false; 17465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17471730e0dd28b3abc660b4e4704cf6d414f7fd4ad6Chris Forbes used = false; 17485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis it_a++; 17495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (!b_at_end && (a_at_end || b_first < a_first)) { 1750bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 0, __LINE__, 1751bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SHADER_CHECKER_INPUT_NOT_PRODUCED, "SC", "Vertex shader consumes input at location %d but not provided", 17525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis b_first)) { 17535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pass = false; 17545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis it_b++; 17565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 17575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned attrib_type = get_format_type(it_a->second->format); 17585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned input_type = get_fundamental_type(vs, it_b->second.type_id); 17595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 176025002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Type checking 17615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (attrib_type != FORMAT_TYPE_UNDEFINED && input_type != FORMAT_TYPE_UNDEFINED && attrib_type != input_type) { 1762bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 1763bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SHADER_CHECKER_INTERFACE_TYPE_MISMATCH, "SC", 17644b5890faffa54a735782a6b0a628a991ddc86944Mike Weiblen "Attribute type of `%s` at location %d does not match vertex shader input type of `%s`", 1765bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski string_VkFormat(it_a->second->format), a_first, describe_type(vs, it_b->second.type_id).c_str())) { 17665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pass = false; 17675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 177025002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // OK! 17711730e0dd28b3abc660b4e4704cf6d414f7fd4ad6Chris Forbes used = true; 17725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis it_b++; 17735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 17765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return pass; 17775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 17785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1779edef66e03ed509994449d598f4fadea1a487d41bChris Forbesstatic bool validate_fs_outputs_against_render_pass(debug_report_data *report_data, shader_module const *fs, 17808da1edac0fbed13831b2f458f27c51e64d6210ffTobin Ehlis spirv_inst_iter entrypoint, VkRenderPassCreateInfo const *rpci, 17818da1edac0fbed13831b2f458f27c51e64d6210ffTobin Ehlis uint32_t subpass_index) { 1782025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes std::map<uint32_t, VkFormat> color_attachments; 17838da1edac0fbed13831b2f458f27c51e64d6210ffTobin Ehlis auto subpass = rpci->pSubpasses[subpass_index]; 17848da1edac0fbed13831b2f458f27c51e64d6210ffTobin Ehlis for (auto i = 0u; i < subpass.colorAttachmentCount; ++i) { 1785d9da90d92748c37962766868f8b0354637672c2aTobin Ehlis uint32_t attachment = subpass.pColorAttachments[i].attachment; 1786cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (attachment == VK_ATTACHMENT_UNUSED) continue; 1787d9da90d92748c37962766868f8b0354637672c2aTobin Ehlis if (rpci->pAttachments[attachment].format != VK_FORMAT_UNDEFINED) { 1788d9da90d92748c37962766868f8b0354637672c2aTobin Ehlis color_attachments[i] = rpci->pAttachments[attachment].format; 1789025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes } 1790025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes } 1791025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes 17925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool pass = true; 17935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 179425002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // TODO: dual source blend index (spv::DecIndex, zero if not provided) 17955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 17963a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes auto outputs = collect_interface_by_location(fs, entrypoint, spv::StorageClassOutput, false); 17975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1798025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes auto it_a = outputs.begin(); 1799025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes auto it_b = color_attachments.begin(); 18005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 180125002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Walk attachment list and outputs together 1802025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes 1803025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes while ((outputs.size() > 0 && it_a != outputs.end()) || (color_attachments.size() > 0 && it_b != color_attachments.end())) { 1804025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes bool a_at_end = outputs.size() == 0 || it_a == outputs.end(); 1805025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes bool b_at_end = color_attachments.size() == 0 || it_b == color_attachments.end(); 18065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1807025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes if (!a_at_end && (b_at_end || it_a->first.first < it_b->first)) { 1808bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 1809bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SHADER_CHECKER_OUTPUT_NOT_CONSUMED, "SC", 1810d79335137b414d5f89284a9ab3e014beb4ada3ebMike Weiblen "fragment shader writes to output location %d with no matching attachment", it_a->first.first)) { 18115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pass = false; 18125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 1813025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes it_a++; 1814025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes } else if (!b_at_end && (a_at_end || it_a->first.first > it_b->first)) { 1815bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 1816bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SHADER_CHECKER_INPUT_NOT_PRODUCED, "SC", "Attachment %d not written by fragment shader", it_b->first)) { 18175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pass = false; 18185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 1819025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes it_b++; 18205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 1821025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes unsigned output_type = get_fundamental_type(fs, it_a->second.type_id); 1822025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes unsigned att_type = get_format_type(it_b->second); 18235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 182425002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Type checking 18255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (att_type != FORMAT_TYPE_UNDEFINED && output_type != FORMAT_TYPE_UNDEFINED && att_type != output_type) { 1826bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 1827bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SHADER_CHECKER_INTERFACE_TYPE_MISMATCH, "SC", 1828d79335137b414d5f89284a9ab3e014beb4ada3ebMike Weiblen "Attachment %d of type `%s` does not match fragment shader output type of `%s`", it_b->first, 1829bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski string_VkFormat(it_b->second), describe_type(fs, it_a->second.type_id).c_str())) { 18305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pass = false; 18315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 18325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 18335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 183425002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // OK! 1835025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes it_a++; 1836025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes it_b++; 18375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 18385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 18395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 18405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return pass; 18415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 18425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 184325002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// For some analyses, we need to know about all ids referenced by the static call tree of a particular entrypoint. This is 184425002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// important for identifying the set of shader resources actually used by an entrypoint, for example. 184525002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// Note: we only explore parts of the image which might actually contain ids we care about for the above analyses. 184625002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// - NOT the shader input/output interfaces. 184725002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// 184825002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// TODO: The set of interesting opcodes here was determined by eyeballing the SPIRV spec. It might be worth 184925002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// converting parts of this to be generated from the machine-readable spec instead. 18503a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbesstatic std::unordered_set<uint32_t> mark_accessible_ids(shader_module const *src, spirv_inst_iter entrypoint) { 18513a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes std::unordered_set<uint32_t> ids; 18525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_set<uint32_t> worklist; 18535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis worklist.insert(entrypoint.word(2)); 18545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 18555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis while (!worklist.empty()) { 18565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto id_iter = worklist.begin(); 18575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto id = *id_iter; 18585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis worklist.erase(id_iter); 18595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 18605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto insn = src->get_def(id); 18615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn == src->end()) { 186225002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // ID is something we didn't collect in build_def_index. that's OK -- we'll stumble across all kinds of things here 186325002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // that we may not care about. 18645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis continue; 18655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 18665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 186725002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Try to add to the output set 18685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!ids.insert(id).second) { 1869cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski continue; // If we already saw this id, we don't want to walk it again. 18705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 18715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 18725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis switch (insn.opcode()) { 1873cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpFunction: 1874cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Scan whole body of the function, enlisting anything interesting 1875cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski while (++insn, insn.opcode() != spv::OpFunctionEnd) { 1876cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski switch (insn.opcode()) { 1877cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpLoad: 1878cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicLoad: 1879cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicExchange: 1880cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicCompareExchange: 1881cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicCompareExchangeWeak: 1882cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicIIncrement: 1883cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicIDecrement: 1884cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicIAdd: 1885cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicISub: 1886cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicSMin: 1887cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicUMin: 1888cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicSMax: 1889cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicUMax: 1890cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicAnd: 1891cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicOr: 1892cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicXor: 1893cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski worklist.insert(insn.word(3)); // ptr 1894cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1895cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpStore: 1896cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicStore: 1897cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski worklist.insert(insn.word(1)); // ptr 1898cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1899cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAccessChain: 1900cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpInBoundsAccessChain: 1901cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski worklist.insert(insn.word(3)); // base ptr 1902cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1903cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpSampledImage: 1904cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSampleImplicitLod: 1905cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSampleExplicitLod: 1906cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSampleDrefImplicitLod: 1907cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSampleDrefExplicitLod: 1908cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSampleProjImplicitLod: 1909cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSampleProjExplicitLod: 1910cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSampleProjDrefImplicitLod: 1911cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSampleProjDrefExplicitLod: 1912cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageFetch: 1913cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageGather: 1914cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageDrefGather: 1915cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageRead: 1916cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImage: 1917cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageQueryFormat: 1918cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageQueryOrder: 1919cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageQuerySizeLod: 1920cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageQuerySize: 1921cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageQueryLod: 1922cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageQueryLevels: 1923cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageQuerySamples: 1924cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSparseSampleImplicitLod: 1925cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSparseSampleExplicitLod: 1926cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSparseSampleDrefImplicitLod: 1927cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSparseSampleDrefExplicitLod: 1928cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSparseSampleProjImplicitLod: 1929cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSparseSampleProjExplicitLod: 1930cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSparseSampleProjDrefImplicitLod: 1931cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSparseSampleProjDrefExplicitLod: 1932cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSparseFetch: 1933cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSparseGather: 1934cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSparseDrefGather: 1935cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageTexelPointer: 1936cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski worklist.insert(insn.word(3)); // Image or sampled image 1937cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1938cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageWrite: 1939cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski worklist.insert(insn.word(1)); // Image -- different operand order to above 1940cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1941cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpFunctionCall: 1942cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski for (uint32_t i = 3; i < insn.len(); i++) { 1943cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski worklist.insert(insn.word(i)); // fn itself, and all args 1944cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 1945cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 19465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1947cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpExtInst: 1948cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski for (uint32_t i = 5; i < insn.len(); i++) { 1949cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski worklist.insert(insn.word(i)); // Operands to ext inst 1950cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 1951cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 19525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 19535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 1954cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 19555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 19565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 19573a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes 19583a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes return ids; 19595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 19605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1961edef66e03ed509994449d598f4fadea1a487d41bChris Forbesstatic bool validate_push_constant_block_against_pipeline(debug_report_data *report_data, 1962416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis std::vector<VkPushConstantRange> const *push_constant_ranges, 19635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis shader_module const *src, spirv_inst_iter type, 19645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkShaderStageFlagBits stage) { 19655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool pass = true; 19665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 196725002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Strip off ptrs etc 19685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis type = get_struct_type(src, type, false); 19695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(type != src->end()); 19705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 197125002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Validate directly off the offsets. this isn't quite correct for arrays and matrices, but is a good first step. 197225002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // TODO: arrays, matrices, weird sizes 19735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto insn : *src) { 19745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.opcode() == spv::OpMemberDecorate && insn.word(1) == type.word(1)) { 19755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.word(3) == spv::DecorationOffset) { 19765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned offset = insn.word(4); 1977cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski auto size = 4; // Bytes; TODO: calculate this based on the type 19785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 19795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool found_range = false; 1980416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis for (auto const &range : *push_constant_ranges) { 19815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (range.offset <= offset && range.offset + range.size >= offset + size) { 19825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis found_range = true; 19835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 19845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if ((range.stageFlags & stage) == 0) { 1985bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 1986bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SHADER_CHECKER_PUSH_CONSTANT_NOT_ACCESSIBLE_FROM_STAGE, "SC", 19875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis "Push constant range covering variable starting at " 19885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis "offset %u not accessible from stage %s", 19895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis offset, string_VkShaderStageFlagBits(stage))) { 19905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pass = false; 19915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 19925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 19935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 19945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis break; 19955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 19965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 19975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 19985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!found_range) { 1999bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 2000bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SHADER_CHECKER_PUSH_CONSTANT_OUT_OF_RANGE, "SC", 20015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis "Push constant range covering variable starting at " 20025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis "offset %u not declared in layout", 20035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis offset)) { 20045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pass = false; 20055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 20065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 20075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 20085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 20095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 20105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 20115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return pass; 20125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 20135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2014edef66e03ed509994449d598f4fadea1a487d41bChris Forbesstatic bool validate_push_constant_usage(debug_report_data *report_data, 2015416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis std::vector<VkPushConstantRange> const *push_constant_ranges, shader_module const *src, 20165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_set<uint32_t> accessible_ids, VkShaderStageFlagBits stage) { 20175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool pass = true; 20185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 20195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto id : accessible_ids) { 20205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto def_insn = src->get_def(id); 20215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (def_insn.opcode() == spv::OpVariable && def_insn.word(3) == spv::StorageClassPushConstant) { 2022416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis pass &= validate_push_constant_block_against_pipeline(report_data, push_constant_ranges, src, 2023416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis src->get_def(def_insn.word(1)), stage); 20245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 20255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 20265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 20275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return pass; 20285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 20295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2030fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis// For given pipelineLayout verify that the set_layout_node at slot.first 2031fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis// has the requested binding at slot.second and return ptr to that binding 2032bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic VkDescriptorSetLayoutBinding const *get_descriptor_binding(PIPELINE_LAYOUT_NODE const *pipelineLayout, 2033bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski descriptor_slot_t slot) { 2034cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!pipelineLayout) return nullptr; 20355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2036cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (slot.first >= pipelineLayout->set_layouts.size()) return nullptr; 20375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2038416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis return pipelineLayout->set_layouts[slot.first]->GetDescriptorSetLayoutBindingPtrFromBinding(slot.second); 20395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 20405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 20415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Check object status for selected flag state 204251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool validate_status(layer_data *dev_data, GLOBAL_CB_NODE *pNode, CBStatusFlags status_mask, VkFlags msg_flags, 20434f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes const char *fail_msg, UNIQUE_VALIDATION_ERROR_CODE const msg_code) { 20443d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis if (!(pNode->status & status_mask)) { 20454f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes char const *const message = validation_error_map[msg_code]; 204651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis return log_msg(dev_data->report_data, msg_flags, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 20474f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes reinterpret_cast<const uint64_t &>(pNode->commandBuffer), __LINE__, msg_code, "DS", 20484f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "command buffer object 0x%p: %s. %s.", pNode->commandBuffer, fail_msg, message); 20495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 2050e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves return false; 20515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 20525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 20535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Retrieve pipeline node ptr for given pipeline object 205451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic PIPELINE_STATE *getPipelineState(layer_data const *dev_data, VkPipeline pipeline) { 205551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis auto it = dev_data->pipelineMap.find(pipeline); 205651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (it == dev_data->pipelineMap.end()) { 2057ea8349eeee76ae2859c10870fd8bd9e60309eb28Chris Forbes return nullptr; 20585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 2059ea8349eeee76ae2859c10870fd8bd9e60309eb28Chris Forbes return it->second; 20605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 20615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 20629a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisRENDER_PASS_STATE *GetRenderPassState(layer_data const *dev_data, VkRenderPass renderpass) { 206351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis auto it = dev_data->renderPassMap.find(renderpass); 206451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (it == dev_data->renderPassMap.end()) { 206516387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes return nullptr; 206616387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes } 2067fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes return it->second.get(); 206816387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes} 206916387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes 20709a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisFRAMEBUFFER_STATE *GetFramebufferState(const layer_data *dev_data, VkFramebuffer framebuffer) { 207151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis auto it = dev_data->frameBufferMap.find(framebuffer); 207251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (it == dev_data->frameBufferMap.end()) { 2073f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes return nullptr; 2074f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes } 207504861caca7eb93a5241b164e8480bb93c826902cTobin Ehlis return it->second.get(); 2076f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes} 2077f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes 20789a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehliscvdescriptorset::DescriptorSetLayout const *GetDescriptorSetLayout(layer_data const *dev_data, VkDescriptorSetLayout dsLayout) { 207951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis auto it = dev_data->descriptorSetLayoutMap.find(dsLayout); 208051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (it == dev_data->descriptorSetLayoutMap.end()) { 208111f1fde2721c198a619e4a22fff60eef9a16fae8Chris Forbes return nullptr; 208211f1fde2721c198a619e4a22fff60eef9a16fae8Chris Forbes } 208311f1fde2721c198a619e4a22fff60eef9a16fae8Chris Forbes return it->second; 208411f1fde2721c198a619e4a22fff60eef9a16fae8Chris Forbes} 208511f1fde2721c198a619e4a22fff60eef9a16fae8Chris Forbes 208651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic PIPELINE_LAYOUT_NODE const *getPipelineLayout(layer_data const *dev_data, VkPipelineLayout pipeLayout) { 208751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis auto it = dev_data->pipelineLayoutMap.find(pipeLayout); 208851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (it == dev_data->pipelineLayoutMap.end()) { 20894a45a42023b281f55953222c1a6c3e80f50e5f2aChris Forbes return nullptr; 20904a45a42023b281f55953222c1a6c3e80f50e5f2aChris Forbes } 20914a45a42023b281f55953222c1a6c3e80f50e5f2aChris Forbes return &it->second; 20924a45a42023b281f55953222c1a6c3e80f50e5f2aChris Forbes} 20934a45a42023b281f55953222c1a6c3e80f50e5f2aChris Forbes 2094e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves// Return true if for a given PSO, the given state enum is dynamic, else return false 20954c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlisstatic bool isDynamic(const PIPELINE_STATE *pPipeline, const VkDynamicState state) { 20965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pPipeline && pPipeline->graphicsPipelineCI.pDynamicState) { 20975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < pPipeline->graphicsPipelineCI.pDynamicState->dynamicStateCount; i++) { 2098cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (state == pPipeline->graphicsPipelineCI.pDynamicState->pDynamicStates[i]) return true; 20995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 21005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 2101e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves return false; 21025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 21035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 21045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Validate state stored as flags at time of draw call 21054f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayesstatic bool validate_draw_state_flags(layer_data *dev_data, GLOBAL_CB_NODE *pCB, const PIPELINE_STATE *pPipe, bool indexed, 21064f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes UNIQUE_VALIDATION_ERROR_CODE const msg_code) { 21079c4006684a13db43f0dbc8d0015a9ef34872ca09Chris Forbes bool result = false; 2108ca546210846c65808717f8875deae39bd227c240Tobin Ehlis if (pPipe->graphicsPipelineCI.pInputAssemblyState && 2109ca546210846c65808717f8875deae39bd227c240Tobin Ehlis ((pPipe->graphicsPipelineCI.pInputAssemblyState->topology == VK_PRIMITIVE_TOPOLOGY_LINE_LIST) || 2110ca546210846c65808717f8875deae39bd227c240Tobin Ehlis (pPipe->graphicsPipelineCI.pInputAssemblyState->topology == VK_PRIMITIVE_TOPOLOGY_LINE_STRIP))) { 21113d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis result |= validate_status(dev_data, pCB, CBSTATUS_LINE_WIDTH_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, 21124f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "Dynamic line width state not set for this command buffer", msg_code); 21133d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 211445824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves if (pPipe->graphicsPipelineCI.pRasterizationState && 211545824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves (pPipe->graphicsPipelineCI.pRasterizationState->depthBiasEnable == VK_TRUE)) { 21163d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis result |= validate_status(dev_data, pCB, CBSTATUS_DEPTH_BIAS_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, 21174f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "Dynamic depth bias state not set for this command buffer", msg_code); 21183d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 21193d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis if (pPipe->blendConstantsEnabled) { 21203d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis result |= validate_status(dev_data, pCB, CBSTATUS_BLEND_CONSTANTS_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, 21214f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "Dynamic blend constants state not set for this command buffer", msg_code); 21223d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 212345824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves if (pPipe->graphicsPipelineCI.pDepthStencilState && 212445824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves (pPipe->graphicsPipelineCI.pDepthStencilState->depthBoundsTestEnable == VK_TRUE)) { 21253d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis result |= validate_status(dev_data, pCB, CBSTATUS_DEPTH_BOUNDS_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, 21264f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "Dynamic depth bounds state not set for this command buffer", msg_code); 21273d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 212845824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves if (pPipe->graphicsPipelineCI.pDepthStencilState && 212945824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves (pPipe->graphicsPipelineCI.pDepthStencilState->stencilTestEnable == VK_TRUE)) { 21303d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis result |= validate_status(dev_data, pCB, CBSTATUS_STENCIL_READ_MASK_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, 21314f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "Dynamic stencil read mask state not set for this command buffer", msg_code); 21323d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis result |= validate_status(dev_data, pCB, CBSTATUS_STENCIL_WRITE_MASK_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, 21334f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "Dynamic stencil write mask state not set for this command buffer", msg_code); 21343d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis result |= validate_status(dev_data, pCB, CBSTATUS_STENCIL_REFERENCE_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, 21354f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "Dynamic stencil reference state not set for this command buffer", msg_code); 21363d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 21371c130ea631a82716dc7334de17767536525f2292Tobin Ehlis if (indexed) { 21383d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis result |= validate_status(dev_data, pCB, CBSTATUS_INDEX_BUFFER_BOUND, VK_DEBUG_REPORT_ERROR_BIT_EXT, 21394f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "Index buffer object not bound to this command buffer when Indexed Draw attempted", msg_code); 21403d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 21414f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes 21425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 21435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 21445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 21455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Verify attachment reference compatibility according to spec 21465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// If one array is larger, treat missing elements of shorter array as VK_ATTACHMENT_UNUSED & other array much match this 21475ca3c071afc98f9144f489b74aa3affaa93633b0Mark Lobodzinski// If both AttachmentReference arrays have requested index, check their corresponding AttachmentDescriptions 21485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// to make sure that format and samples counts match. 21495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// If not, they are not compatible. 21505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic bool attachment_references_compatible(const uint32_t index, const VkAttachmentReference *pPrimary, 21515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const uint32_t primaryCount, const VkAttachmentDescription *pPrimaryAttachments, 21525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkAttachmentReference *pSecondary, const uint32_t secondaryCount, 21535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkAttachmentDescription *pSecondaryAttachments) { 2154e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis // Check potential NULL cases first to avoid nullptr issues later 2155e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis if (pPrimary == nullptr) { 2156e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis if (pSecondary == nullptr) { 2157e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis return true; 2158e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis } 2159e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis return false; 2160e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis } else if (pSecondary == nullptr) { 2161e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis return false; 2162e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis } 2163cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (index >= primaryCount) { // Check secondary as if primary is VK_ATTACHMENT_UNUSED 2164cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (VK_ATTACHMENT_UNUSED == pSecondary[index].attachment) return true; 2165cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else if (index >= secondaryCount) { // Check primary as if secondary is VK_ATTACHMENT_UNUSED 2166cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (VK_ATTACHMENT_UNUSED == pPrimary[index].attachment) return true; 2167cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else { // Format and sample count must match 21685ca3c071afc98f9144f489b74aa3affaa93633b0Mark Lobodzinski if ((pPrimary[index].attachment == VK_ATTACHMENT_UNUSED) && (pSecondary[index].attachment == VK_ATTACHMENT_UNUSED)) { 21695ca3c071afc98f9144f489b74aa3affaa93633b0Mark Lobodzinski return true; 21705ca3c071afc98f9144f489b74aa3affaa93633b0Mark Lobodzinski } else if ((pPrimary[index].attachment == VK_ATTACHMENT_UNUSED) || (pSecondary[index].attachment == VK_ATTACHMENT_UNUSED)) { 21715ca3c071afc98f9144f489b74aa3affaa93633b0Mark Lobodzinski return false; 21725ca3c071afc98f9144f489b74aa3affaa93633b0Mark Lobodzinski } 21735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if ((pPrimaryAttachments[pPrimary[index].attachment].format == 21745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pSecondaryAttachments[pSecondary[index].attachment].format) && 21755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (pPrimaryAttachments[pPrimary[index].attachment].samples == 21765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pSecondaryAttachments[pSecondary[index].attachment].samples)) 21775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return true; 21785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 21795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Format and sample counts didn't match 21805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 21815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 2182a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis// TODO : Scrub verify_renderpass_compatibility() and validateRenderPassCompatibility() and unify them and/or share code 21838da1edac0fbed13831b2f458f27c51e64d6210ffTobin Ehlis// For given primary RenderPass object and secondry RenderPassCreateInfo, verify that they're compatible 218451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool verify_renderpass_compatibility(const layer_data *dev_data, const VkRenderPassCreateInfo *primaryRPCI, 21858da1edac0fbed13831b2f458f27c51e64d6210ffTobin Ehlis const VkRenderPassCreateInfo *secondaryRPCI, string &errorMsg) { 21865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (primaryRPCI->subpassCount != secondaryRPCI->subpassCount) { 2187c07fa78efa7d4edfaa4ffbb0c2046ee8154b27beChris Forbes stringstream errorStr; 21885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis errorStr << "RenderPass for primary cmdBuffer has " << primaryRPCI->subpassCount 21895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis << " subpasses but renderPass for secondary cmdBuffer has " << secondaryRPCI->subpassCount << " subpasses."; 21905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis errorMsg = errorStr.str(); 21915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 21925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 21935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t spIndex = 0; 21945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (spIndex = 0; spIndex < primaryRPCI->subpassCount; ++spIndex) { 21955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // For each subpass, verify that corresponding color, input, resolve & depth/stencil attachment references are compatible 21965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t primaryColorCount = primaryRPCI->pSubpasses[spIndex].colorAttachmentCount; 21975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t secondaryColorCount = secondaryRPCI->pSubpasses[spIndex].colorAttachmentCount; 21985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t colorMax = std::max(primaryColorCount, secondaryColorCount); 21995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t cIdx = 0; cIdx < colorMax; ++cIdx) { 22005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!attachment_references_compatible(cIdx, primaryRPCI->pSubpasses[spIndex].pColorAttachments, primaryColorCount, 22015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis primaryRPCI->pAttachments, secondaryRPCI->pSubpasses[spIndex].pColorAttachments, 22025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis secondaryColorCount, secondaryRPCI->pAttachments)) { 2203c07fa78efa7d4edfaa4ffbb0c2046ee8154b27beChris Forbes stringstream errorStr; 22045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis errorStr << "color attachments at index " << cIdx << " of subpass index " << spIndex << " are not compatible."; 22055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis errorMsg = errorStr.str(); 22065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 22075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (!attachment_references_compatible(cIdx, primaryRPCI->pSubpasses[spIndex].pResolveAttachments, 22085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis primaryColorCount, primaryRPCI->pAttachments, 22095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis secondaryRPCI->pSubpasses[spIndex].pResolveAttachments, 22105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis secondaryColorCount, secondaryRPCI->pAttachments)) { 2211c07fa78efa7d4edfaa4ffbb0c2046ee8154b27beChris Forbes stringstream errorStr; 22125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis errorStr << "resolve attachments at index " << cIdx << " of subpass index " << spIndex << " are not compatible."; 22135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis errorMsg = errorStr.str(); 22145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 22155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 22165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 2217fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes 2218bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (!attachment_references_compatible(0, primaryRPCI->pSubpasses[spIndex].pDepthStencilAttachment, 1, 2219bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski primaryRPCI->pAttachments, secondaryRPCI->pSubpasses[spIndex].pDepthStencilAttachment, 2220fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes 1, secondaryRPCI->pAttachments)) { 2221c07fa78efa7d4edfaa4ffbb0c2046ee8154b27beChris Forbes stringstream errorStr; 2222fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes errorStr << "depth/stencil attachments of subpass index " << spIndex << " are not compatible."; 2223fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes errorMsg = errorStr.str(); 2224fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes return false; 2225fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes } 2226fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes 22275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t primaryInputCount = primaryRPCI->pSubpasses[spIndex].inputAttachmentCount; 22285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t secondaryInputCount = secondaryRPCI->pSubpasses[spIndex].inputAttachmentCount; 22295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t inputMax = std::max(primaryInputCount, secondaryInputCount); 22305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < inputMax; ++i) { 22315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!attachment_references_compatible(i, primaryRPCI->pSubpasses[spIndex].pInputAttachments, primaryColorCount, 22325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis primaryRPCI->pAttachments, secondaryRPCI->pSubpasses[spIndex].pInputAttachments, 22335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis secondaryColorCount, secondaryRPCI->pAttachments)) { 2234c07fa78efa7d4edfaa4ffbb0c2046ee8154b27beChris Forbes stringstream errorStr; 22355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis errorStr << "input attachments at index " << i << " of subpass index " << spIndex << " are not compatible."; 22365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis errorMsg = errorStr.str(); 22375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 22385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 22395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 22405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 22415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return true; 22425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 22435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2244397d27da37095073c8b86f9ff5289d0a39ce486eTobin Ehlis// For given cvdescriptorset::DescriptorSet, verify that its Set is compatible w/ the setLayout corresponding to 2245397d27da37095073c8b86f9ff5289d0a39ce486eTobin Ehlis// pipelineLayout[layoutIndex] 224651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool verify_set_layout_compatibility(layer_data *dev_data, const cvdescriptorset::DescriptorSet *descriptor_set, 224769b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis PIPELINE_LAYOUT_NODE const *pipeline_layout, const uint32_t layoutIndex, 224869b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis string &errorMsg) { 2249416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis auto num_sets = pipeline_layout->set_layouts.size(); 22509b5d124aff50234cb0450e1b805baef577c90d83Tobin Ehlis if (layoutIndex >= num_sets) { 2251c07fa78efa7d4edfaa4ffbb0c2046ee8154b27beChris Forbes stringstream errorStr; 225269b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis errorStr << "VkPipelineLayout (" << pipeline_layout->layout << ") only contains " << num_sets 225369b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis << " setLayouts corresponding to sets 0-" << num_sets - 1 << ", but you're attempting to bind set to index " 225469b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis << layoutIndex; 22555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis errorMsg = errorStr.str(); 22565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 22575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 2258416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis auto layout_node = pipeline_layout->set_layouts[layoutIndex]; 22591c130ea631a82716dc7334de17767536525f2292Tobin Ehlis return descriptor_set->IsCompatible(layout_node, &errorMsg); 22605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 22615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 22625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Validate that data for each specialization entry is fully contained within the buffer. 2263edef66e03ed509994449d598f4fadea1a487d41bChris Forbesstatic bool validate_specialization_offsets(debug_report_data *report_data, VkPipelineShaderStageCreateInfo const *info) { 2264e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool pass = true; 22655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 22665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkSpecializationInfo const *spec = info->pSpecializationInfo; 22675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 22685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (spec) { 22695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto i = 0u; i < spec->mapEntryCount; i++) { 22704f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes // TODO: This is a good place for VALIDATION_ERROR_00589. 22715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (spec->pMapEntries[i].offset + spec->pMapEntries[i].size > spec->dataSize) { 22724f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 0, __LINE__, 22734f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes VALIDATION_ERROR_00590, "SC", 22745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis "Specialization entry %u (for constant id %u) references memory outside provided " 22755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis "specialization data (bytes %u.." PRINTF_SIZE_T_SPECIFIER "; " PRINTF_SIZE_T_SPECIFIER 22764f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes " bytes provided). %s.", 22775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis i, spec->pMapEntries[i].constantID, spec->pMapEntries[i].offset, 22784f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes spec->pMapEntries[i].offset + spec->pMapEntries[i].size - 1, spec->dataSize, 22794f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes validation_error_map[VALIDATION_ERROR_00590])) { 2280e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves pass = false; 22815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 22825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 22835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 22845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 22855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 22865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return pass; 22875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 22885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2289bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic bool descriptor_type_match(shader_module const *module, uint32_t type_id, VkDescriptorType descriptor_type, 2290bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski unsigned &descriptor_count) { 22915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto type = module->get_def(type_id); 22925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 22931b8c581791ac3c05d7829e04a2d8ecb964b8f2a6Chris Forbes descriptor_count = 1; 22941b8c581791ac3c05d7829e04a2d8ecb964b8f2a6Chris Forbes 229525002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Strip off any array or ptrs. Where we remove array levels, adjust the descriptor count for each dimension. 22965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis while (type.opcode() == spv::OpTypeArray || type.opcode() == spv::OpTypePointer) { 22977b892d2fc502b57d26dc9bff61b0f23cccc595fdChris Forbes if (type.opcode() == spv::OpTypeArray) { 22987b892d2fc502b57d26dc9bff61b0f23cccc595fdChris Forbes descriptor_count *= get_constant_value(module, type.word(3)); 22997b892d2fc502b57d26dc9bff61b0f23cccc595fdChris Forbes type = module->get_def(type.word(2)); 2300bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski } else { 23017b892d2fc502b57d26dc9bff61b0f23cccc595fdChris Forbes type = module->get_def(type.word(3)); 23027b892d2fc502b57d26dc9bff61b0f23cccc595fdChris Forbes } 23035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 23045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 23055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis switch (type.opcode()) { 2306cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeStruct: { 2307cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski for (auto insn : *module) { 2308cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (insn.opcode() == spv::OpDecorate && insn.word(1) == type.word(1)) { 2309cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (insn.word(2) == spv::DecorationBlock) { 2310cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER || 2311cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; 2312cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else if (insn.word(2) == spv::DecorationBufferBlock) { 2313cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER || 2314cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC; 2315cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 23165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 23175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 23185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2319cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Invalid 2320cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return false; 2321cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 23225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2323cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeSampler: 2324cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return descriptor_type == VK_DESCRIPTOR_TYPE_SAMPLER || descriptor_type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 23255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2326cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeSampledImage: 2327cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER) { 2328cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Slight relaxation for some GLSL historical madness: samplerBuffer doesn't really have a sampler, and a texel 2329cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // buffer descriptor doesn't really provide one. Allow this slight mismatch. 2330cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski auto image_type = module->get_def(type.word(2)); 2331cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski auto dim = image_type.word(3); 2332cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski auto sampled = image_type.word(7); 2333cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return dim == spv::DimBuffer && sampled == 1; 2334cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 2335cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return descriptor_type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 23365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2337cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeImage: { 2338cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Many descriptor types backing image types-- depends on dimension and whether the image will be used with a sampler. 2339cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // SPIRV for Vulkan requires that sampled be 1 or 2 -- leaving the decision to runtime is unacceptable. 2340cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski auto dim = type.word(3); 2341cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski auto sampled = type.word(7); 23425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2343cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dim == spv::DimSubpassData) { 2344cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return descriptor_type == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; 2345cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else if (dim == spv::DimBuffer) { 2346cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (sampled == 1) { 2347cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; 2348cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else { 2349cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; 2350cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 2351cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else if (sampled == 1) { 2352cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return descriptor_type == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE || 2353cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski descriptor_type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 23545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 2355cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; 23565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 23575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 23585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2359cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // We shouldn't really see any other junk types -- but if we do, they're a mismatch. 2360cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 2361cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return false; // Mismatch 23625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 23635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 23645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 23654110a6be7a8a287d459475926985f71c27d01298Chris Forbesstatic bool require_feature(debug_report_data *report_data, VkBool32 feature, char const *feature_name) { 2366a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes if (!feature) { 2367bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 2368cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski SHADER_CHECKER_FEATURE_NOT_ENABLED, "SC", 2369cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Shader requires VkPhysicalDeviceFeatures::%s but is not " 2370cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "enabled on the device", 2371a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes feature_name)) { 2372a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes return false; 2373a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes } 2374a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes } 2375a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2376a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes return true; 2377a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes} 2378a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 237969f9a551bfb1fd5334950f9685c12c5adda23dfbChris Forbesstatic bool validate_shader_capabilities(debug_report_data *report_data, shader_module const *src, 238069f9a551bfb1fd5334950f9685c12c5adda23dfbChris Forbes VkPhysicalDeviceFeatures const *enabledFeatures) { 2381e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool pass = true; 2382a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2383a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes for (auto insn : *src) { 2384a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes if (insn.opcode() == spv::OpCapability) { 2385a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes switch (insn.word(1)) { 2386cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityMatrix: 2387cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityShader: 2388cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityInputAttachment: 2389cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilitySampled1D: 2390cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityImage1D: 2391cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilitySampledBuffer: 2392cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityImageBuffer: 2393cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityImageQuery: 2394cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityDerivativeControl: 2395cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Always supported by a Vulkan 1.0 implementation -- no feature bits. 2396cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2397a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2398cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityGeometry: 2399cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->geometryShader, "geometryShader"); 2400cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2401a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2402cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityTessellation: 2403cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->tessellationShader, "tessellationShader"); 2404cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2405a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2406cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityFloat64: 2407cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->shaderFloat64, "shaderFloat64"); 2408cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2409a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2410cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityInt64: 2411cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->shaderInt64, "shaderInt64"); 2412cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2413a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2414cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityTessellationPointSize: 2415cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityGeometryPointSize: 2416cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->shaderTessellationAndGeometryPointSize, 2417cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "shaderTessellationAndGeometryPointSize"); 2418cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2419a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2420cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityImageGatherExtended: 2421cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->shaderImageGatherExtended, "shaderImageGatherExtended"); 2422cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2423a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2424cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityStorageImageMultisample: 2425cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->shaderStorageImageMultisample, 2426cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "shaderStorageImageMultisample"); 2427cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2428a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2429cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityUniformBufferArrayDynamicIndexing: 2430cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->shaderUniformBufferArrayDynamicIndexing, 2431cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "shaderUniformBufferArrayDynamicIndexing"); 2432cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2433a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2434cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilitySampledImageArrayDynamicIndexing: 2435cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->shaderSampledImageArrayDynamicIndexing, 2436cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "shaderSampledImageArrayDynamicIndexing"); 2437cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2438a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2439cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityStorageBufferArrayDynamicIndexing: 2440cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->shaderStorageBufferArrayDynamicIndexing, 2441cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "shaderStorageBufferArrayDynamicIndexing"); 2442cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2443a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2444cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityStorageImageArrayDynamicIndexing: 2445cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->shaderStorageImageArrayDynamicIndexing, 2446cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "shaderStorageImageArrayDynamicIndexing"); 2447cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2448a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2449cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityClipDistance: 2450cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->shaderClipDistance, "shaderClipDistance"); 2451cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2452a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2453cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityCullDistance: 2454cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->shaderCullDistance, "shaderCullDistance"); 2455cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2456a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2457cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityImageCubeArray: 2458cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->imageCubeArray, "imageCubeArray"); 2459cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2460a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2461cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilitySampleRateShading: 2462cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->sampleRateShading, "sampleRateShading"); 2463cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2464a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2465cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilitySparseResidency: 2466cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->shaderResourceResidency, "shaderResourceResidency"); 2467cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2468a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2469cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityMinLod: 2470cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->shaderResourceMinLod, "shaderResourceMinLod"); 2471cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2472a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2473cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilitySampledCubeArray: 2474cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->imageCubeArray, "imageCubeArray"); 2475cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2476a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2477cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityImageMSArray: 2478cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->shaderStorageImageMultisample, 2479cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "shaderStorageImageMultisample"); 2480cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2481a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2482cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityStorageImageExtendedFormats: 2483cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->shaderStorageImageExtendedFormats, 2484cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "shaderStorageImageExtendedFormats"); 2485cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2486a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2487cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityInterpolationFunction: 2488cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->sampleRateShading, "sampleRateShading"); 2489cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2490a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2491cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityStorageImageReadWithoutFormat: 2492cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->shaderStorageImageReadWithoutFormat, 2493cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "shaderStorageImageReadWithoutFormat"); 2494cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2495a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2496cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityStorageImageWriteWithoutFormat: 2497cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->shaderStorageImageWriteWithoutFormat, 2498cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "shaderStorageImageWriteWithoutFormat"); 2499cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2500a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2501cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityMultiViewport: 2502cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->multiViewport, "multiViewport"); 2503cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2504a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2505cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 2506cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 2507cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski SHADER_CHECKER_BAD_CAPABILITY, "SC", "Shader declares capability %u, not supported in Vulkan.", 2508cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski insn.word(1))) 2509cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass = false; 2510cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2511a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes } 2512a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes } 2513a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes } 2514a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2515a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes return pass; 2516a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes} 2517a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2518b2a61f3cd17c68887759817059fa1872f1e1464aChris Forbesstatic uint32_t descriptor_type_to_reqs(shader_module const *module, uint32_t type_id) { 25192aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes auto type = module->get_def(type_id); 25202aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes 25212aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes while (true) { 25222aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes switch (type.opcode()) { 2523cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeArray: 2524cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeSampledImage: 2525cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski type = module->get_def(type.word(2)); 2526cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2527cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypePointer: 2528cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski type = module->get_def(type.word(3)); 2529cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2530cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeImage: { 2531cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski auto dim = type.word(3); 2532cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski auto arrayed = type.word(5); 2533cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski auto msaa = type.word(6); 2534cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski 2535cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski switch (dim) { 2536cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::Dim1D: 2537cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return arrayed ? DESCRIPTOR_REQ_VIEW_TYPE_1D_ARRAY : DESCRIPTOR_REQ_VIEW_TYPE_1D; 2538cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::Dim2D: 2539cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return (msaa ? DESCRIPTOR_REQ_MULTI_SAMPLE : DESCRIPTOR_REQ_SINGLE_SAMPLE) | 2540cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski (arrayed ? DESCRIPTOR_REQ_VIEW_TYPE_2D_ARRAY : DESCRIPTOR_REQ_VIEW_TYPE_2D); 2541cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::Dim3D: 2542cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return DESCRIPTOR_REQ_VIEW_TYPE_3D; 2543cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::DimCube: 2544cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return arrayed ? DESCRIPTOR_REQ_VIEW_TYPE_CUBE_ARRAY : DESCRIPTOR_REQ_VIEW_TYPE_CUBE; 2545cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::DimSubpassData: 2546cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return msaa ? DESCRIPTOR_REQ_MULTI_SAMPLE : DESCRIPTOR_REQ_SINGLE_SAMPLE; 2547cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: // buffer, etc. 2548cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return 0; 2549cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 25502aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes } 2551cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 2552cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return 0; 25532aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes } 25542aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes } 2555b2a61f3cd17c68887759817059fa1872f1e1464aChris Forbes} 2556b2a61f3cd17c68887759817059fa1872f1e1464aChris Forbes 2557cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskistatic bool validate_pipeline_shader_stage( 2558cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski debug_report_data *report_data, VkPipelineShaderStageCreateInfo const *pStage, PIPELINE_STATE *pipeline, 2559cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski shader_module **out_module, spirv_inst_iter *out_entrypoint, VkPhysicalDeviceFeatures const *enabledFeatures, 2560cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski std::unordered_map<VkShaderModule, std::unique_ptr<shader_module>> const &shaderModuleMap) { 2561e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool pass = true; 256269f9a551bfb1fd5334950f9685c12c5adda23dfbChris Forbes auto module_it = shaderModuleMap.find(pStage->module); 256369f9a551bfb1fd5334950f9685c12c5adda23dfbChris Forbes auto module = *out_module = module_it->second.get(); 256478be5018e238bd464b1f1c55138df277c0c18922Chris Forbes 2565c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski if (!module->has_valid_spirv) return pass; 2566c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski 256725002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Find the entrypoint 256878be5018e238bd464b1f1c55138df277c0c18922Chris Forbes auto entrypoint = *out_entrypoint = find_entrypoint(module, pStage->pName, pStage->stage); 256978be5018e238bd464b1f1c55138df277c0c18922Chris Forbes if (entrypoint == module->end()) { 25704f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, VALIDATION_ERROR_00510, 25714f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "SC", "No entrypoint found named `%s` for stage %s. %s.", pStage->pName, 25724f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes string_VkShaderStageFlagBits(pStage->stage), validation_error_map[VALIDATION_ERROR_00510])) { 2573cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return false; // no point continuing beyond here, any analysis is just going to be garbage. 257478be5018e238bd464b1f1c55138df277c0c18922Chris Forbes } 257578be5018e238bd464b1f1c55138df277c0c18922Chris Forbes } 257678be5018e238bd464b1f1c55138df277c0c18922Chris Forbes 257725002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Validate shader capabilities against enabled device features 2578557cdd5218accf51ca894a14b7c6eeeb733f5cbbChris Forbes pass &= validate_shader_capabilities(report_data, module, enabledFeatures); 257978be5018e238bd464b1f1c55138df277c0c18922Chris Forbes 258025002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Mark accessible ids 25813a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes auto accessible_ids = mark_accessible_ids(module, entrypoint); 258278be5018e238bd464b1f1c55138df277c0c18922Chris Forbes 258325002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Validate descriptor set layout against what the entrypoint actually uses 25843a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes auto descriptor_uses = collect_interface_by_descriptor_slot(report_data, module, accessible_ids); 258578be5018e238bd464b1f1c55138df277c0c18922Chris Forbes 25862e0eca3d6fad72a29ae072e3895e29a2d2d66476Tobin Ehlis auto pipelineLayout = pipeline->pipeline_layout; 2587ed399f66e0512ef077d0e0a7cb903248726d2424Chris Forbes 25880cfa9c3a1747749777581684536218f83c3977a9Chris Forbes pass &= validate_specialization_offsets(report_data, pStage); 2589416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis pass &= validate_push_constant_usage(report_data, &pipelineLayout.push_constant_ranges, module, accessible_ids, pStage->stage); 259078be5018e238bd464b1f1c55138df277c0c18922Chris Forbes 259125002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Validate descriptor use 259278be5018e238bd464b1f1c55138df277c0c18922Chris Forbes for (auto use : descriptor_uses) { 259378be5018e238bd464b1f1c55138df277c0c18922Chris Forbes // While validating shaders capture which slots are used by the pipeline 2594bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto &reqs = pipeline->active_slots[use.first.first][use.first.second]; 2595b2a61f3cd17c68887759817059fa1872f1e1464aChris Forbes reqs = descriptor_req(reqs | descriptor_type_to_reqs(module, use.second.type_id)); 259678be5018e238bd464b1f1c55138df277c0c18922Chris Forbes 259725002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Verify given pipelineLayout has requested setLayout with requested binding 2598c8268861aaa8f9c47920065d6323e4609e5081b0Tobin Ehlis const auto &binding = get_descriptor_binding(&pipelineLayout, use.first); 259978be5018e238bd464b1f1c55138df277c0c18922Chris Forbes unsigned required_descriptor_count; 260078be5018e238bd464b1f1c55138df277c0c18922Chris Forbes 260178be5018e238bd464b1f1c55138df277c0c18922Chris Forbes if (!binding) { 2602bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 2603bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SHADER_CHECKER_MISSING_DESCRIPTOR, "SC", 260478be5018e238bd464b1f1c55138df277c0c18922Chris Forbes "Shader uses descriptor slot %u.%u (used as type `%s`) but not declared in pipeline layout", 260578be5018e238bd464b1f1c55138df277c0c18922Chris Forbes use.first.first, use.first.second, describe_type(module, use.second.type_id).c_str())) { 2606e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves pass = false; 260778be5018e238bd464b1f1c55138df277c0c18922Chris Forbes } 260878be5018e238bd464b1f1c55138df277c0c18922Chris Forbes } else if (~binding->stageFlags & pStage->stage) { 2609bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 0, __LINE__, 2610cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski SHADER_CHECKER_DESCRIPTOR_NOT_ACCESSIBLE_FROM_STAGE, "SC", 2611cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Shader uses descriptor slot %u.%u (used " 2612cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "as type `%s`) but descriptor not " 2613cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "accessible from stage %s", 2614fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis use.first.first, use.first.second, describe_type(module, use.second.type_id).c_str(), 261578be5018e238bd464b1f1c55138df277c0c18922Chris Forbes string_VkShaderStageFlagBits(pStage->stage))) { 2616e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves pass = false; 261778be5018e238bd464b1f1c55138df277c0c18922Chris Forbes } 2618bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski } else if (!descriptor_type_match(module, use.second.type_id, binding->descriptorType, required_descriptor_count)) { 2619557cdd5218accf51ca894a14b7c6eeeb733f5cbbChris Forbes if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 2620cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski SHADER_CHECKER_DESCRIPTOR_TYPE_MISMATCH, "SC", 2621cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Type mismatch on descriptor slot " 2622cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%u.%u (used as type `%s`) but " 2623cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "descriptor of type %s", 2624fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis use.first.first, use.first.second, describe_type(module, use.second.type_id).c_str(), 262578be5018e238bd464b1f1c55138df277c0c18922Chris Forbes string_VkDescriptorType(binding->descriptorType))) { 2626e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves pass = false; 262778be5018e238bd464b1f1c55138df277c0c18922Chris Forbes } 262878be5018e238bd464b1f1c55138df277c0c18922Chris Forbes } else if (binding->descriptorCount < required_descriptor_count) { 2629557cdd5218accf51ca894a14b7c6eeeb733f5cbbChris Forbes if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 2630fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis SHADER_CHECKER_DESCRIPTOR_TYPE_MISMATCH, "SC", 263178be5018e238bd464b1f1c55138df277c0c18922Chris Forbes "Shader expects at least %u descriptors for binding %u.%u (used as type `%s`) but only %u provided", 263278be5018e238bd464b1f1c55138df277c0c18922Chris Forbes required_descriptor_count, use.first.first, use.first.second, 2633fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis describe_type(module, use.second.type_id).c_str(), binding->descriptorCount)) { 2634e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves pass = false; 263578be5018e238bd464b1f1c55138df277c0c18922Chris Forbes } 263678be5018e238bd464b1f1c55138df277c0c18922Chris Forbes } 263778be5018e238bd464b1f1c55138df277c0c18922Chris Forbes } 263878be5018e238bd464b1f1c55138df277c0c18922Chris Forbes 263925002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Validate use of input attachments against subpass structure 2640c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes if (pStage->stage == VK_SHADER_STAGE_FRAGMENT_BIT) { 26413a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes auto input_attachment_uses = collect_interface_by_input_attachment_index(report_data, module, accessible_ids); 2642c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes 2643c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes auto rpci = pipeline->render_pass_ci.ptr(); 2644c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes auto subpass = pipeline->graphicsPipelineCI.subpass; 2645c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes 2646c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes for (auto use : input_attachment_uses) { 2647c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes auto input_attachments = rpci->pSubpasses[subpass].pInputAttachments; 2648bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto index = (input_attachments && use.first < rpci->pSubpasses[subpass].inputAttachmentCount) 2649bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski ? input_attachments[use.first].attachment 2650bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski : VK_ATTACHMENT_UNUSED; 2651c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes 2652c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes if (index == VK_ATTACHMENT_UNUSED) { 2653c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 2654c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes SHADER_CHECKER_MISSING_INPUT_ATTACHMENT, "SC", 2655bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "Shader consumes input attachment index %d but not provided in subpass", use.first)) { 2656c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes pass = false; 2657c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes } 2658bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski } else if (get_format_type(rpci->pAttachments[index].format) != get_fundamental_type(module, use.second.type_id)) { 2659eeb9f6a27f1acc11e54080fb3bcda7b513b5c89fChris Forbes if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 2660eeb9f6a27f1acc11e54080fb3bcda7b513b5c89fChris Forbes SHADER_CHECKER_INPUT_ATTACHMENT_TYPE_MISMATCH, "SC", 2661bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "Subpass input attachment %u format of %s does not match type used in shader `%s`", use.first, 2662bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski string_VkFormat(rpci->pAttachments[index].format), describe_type(module, use.second.type_id).c_str())) { 2663eeb9f6a27f1acc11e54080fb3bcda7b513b5c89fChris Forbes pass = false; 2664eeb9f6a27f1acc11e54080fb3bcda7b513b5c89fChris Forbes } 2665eeb9f6a27f1acc11e54080fb3bcda7b513b5c89fChris Forbes } 2666c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes } 2667c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes } 2668c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes 266978be5018e238bd464b1f1c55138df277c0c18922Chris Forbes return pass; 267078be5018e238bd464b1f1c55138df277c0c18922Chris Forbes} 267178be5018e238bd464b1f1c55138df277c0c18922Chris Forbes 2672a61b537fcb6a4f7b92cd217b3964ad7a48109da1Tobin Ehlis// Validate that the shaders used by the given pipeline and store the active_slots 2673a61b537fcb6a4f7b92cd217b3964ad7a48109da1Tobin Ehlis// that are actually used by the pipeline into pPipeline->active_slots 2674cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskistatic bool validate_and_capture_pipeline_shader_state( 2675cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski debug_report_data *report_data, PIPELINE_STATE *pPipeline, VkPhysicalDeviceFeatures const *enabledFeatures, 2676cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski std::unordered_map<VkShaderModule, unique_ptr<shader_module>> const &shaderModuleMap) { 26776660d6f3e4e4c895063e8d99098162bd2f508b24Chris Forbes auto pCreateInfo = pPipeline->graphicsPipelineCI.ptr(); 26785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis int vertex_stage = get_shader_stage_id(VK_SHADER_STAGE_VERTEX_BIT); 26795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis int fragment_stage = get_shader_stage_id(VK_SHADER_STAGE_FRAGMENT_BIT); 26805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 26815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis shader_module *shaders[5]; 26825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis memset(shaders, 0, sizeof(shaders)); 26835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis spirv_inst_iter entrypoints[5]; 26845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis memset(entrypoints, 0, sizeof(entrypoints)); 26855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkPipelineVertexInputStateCreateInfo const *vi = 0; 2686e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool pass = true; 26875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 26885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->stageCount; i++) { 26896660d6f3e4e4c895063e8d99098162bd2f508b24Chris Forbes auto pStage = &pCreateInfo->pStages[i]; 269078be5018e238bd464b1f1c55138df277c0c18922Chris Forbes auto stage_id = get_shader_stage_id(pStage->stage); 2691bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pass &= validate_pipeline_shader_stage(report_data, pStage, pPipeline, &shaders[stage_id], &entrypoints[stage_id], 269269f9a551bfb1fd5334950f9685c12c5adda23dfbChris Forbes enabledFeatures, shaderModuleMap); 26935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 26945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2695d5365427feb4a6c16371ecb651afa37b89dabd96Chris Forbes // if the shader stages are no good individually, cross-stage validation is pointless. 2696cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!pass) return false; 2697b7476f4c4998ae20e579bd2d134667b71acdbf91Chris Forbes 26985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis vi = pCreateInfo->pVertexInputState; 26995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 27005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (vi) { 2701e4be8c69231df45752686575f22168b6d0fc5687Chris Forbes pass &= validate_vi_consistency(report_data, vi); 27025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 27035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2704c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski if (shaders[vertex_stage] && shaders[vertex_stage]->has_valid_spirv) { 2705e4be8c69231df45752686575f22168b6d0fc5687Chris Forbes pass &= validate_vi_against_vs_inputs(report_data, vi, shaders[vertex_stage], entrypoints[vertex_stage]); 27065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 27075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 27085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis int producer = get_shader_stage_id(VK_SHADER_STAGE_VERTEX_BIT); 27095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis int consumer = get_shader_stage_id(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT); 27105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 27115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis while (!shaders[producer] && producer != fragment_stage) { 27125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis producer++; 27135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis consumer++; 27145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 27155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 27165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (; producer != fragment_stage && consumer <= fragment_stage; consumer++) { 27175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(shaders[producer]); 2718c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski if (shaders[consumer] && shaders[consumer]->has_valid_spirv && shaders[producer]->has_valid_spirv) { 2719bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pass &= validate_interface_between_stages(report_data, shaders[producer], entrypoints[producer], 2720bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &shader_stage_attribs[producer], shaders[consumer], entrypoints[consumer], 2721bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &shader_stage_attribs[consumer]); 27225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 27235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis producer = consumer; 27245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 27255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 27265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2727c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski if (shaders[fragment_stage] && shaders[fragment_stage]->has_valid_spirv) { 2728e4be8c69231df45752686575f22168b6d0fc5687Chris Forbes pass &= validate_fs_outputs_against_render_pass(report_data, shaders[fragment_stage], entrypoints[fragment_stage], 27298da1edac0fbed13831b2f458f27c51e64d6210ffTobin Ehlis pPipeline->render_pass_ci.ptr(), pCreateInfo->subpass); 27305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 27315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 27325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return pass; 27335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 27345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 27354c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlisstatic bool validate_compute_pipeline(debug_report_data *report_data, PIPELINE_STATE *pPipeline, 27364c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis VkPhysicalDeviceFeatures const *enabledFeatures, 27374c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis std::unordered_map<VkShaderModule, unique_ptr<shader_module>> const &shaderModuleMap) { 27386660d6f3e4e4c895063e8d99098162bd2f508b24Chris Forbes auto pCreateInfo = pPipeline->computePipelineCI.ptr(); 273903857e826cdc6e8d814137fb3245596ca1cb7bc7Chris Forbes 274003857e826cdc6e8d814137fb3245596ca1cb7bc7Chris Forbes shader_module *module; 274103857e826cdc6e8d814137fb3245596ca1cb7bc7Chris Forbes spirv_inst_iter entrypoint; 274203857e826cdc6e8d814137fb3245596ca1cb7bc7Chris Forbes 2743bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski return validate_pipeline_shader_stage(report_data, &pCreateInfo->stage, pPipeline, &module, &entrypoint, enabledFeatures, 2744bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski shaderModuleMap); 274503857e826cdc6e8d814137fb3245596ca1cb7bc7Chris Forbes} 27465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Return Set node ptr for specified set or else NULL 27479a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehliscvdescriptorset::DescriptorSet *GetSetNode(const layer_data *dev_data, VkDescriptorSet set) { 274851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis auto set_it = dev_data->setMap.find(set); 274951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (set_it == dev_data->setMap.end()) { 27505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return NULL; 27515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 2752104ab082916e41467ef60baaab7a5a8b2e02c59cTobin Ehlis return set_it->second; 27535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 27545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2755eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young// For given pipeline, return number of MSAA samples, or one if MSAA disabled 27564c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlisstatic VkSampleCountFlagBits getNumSamples(PIPELINE_STATE const *pipe) { 2757ea8349eeee76ae2859c10870fd8bd9e60309eb28Chris Forbes if (pipe->graphicsPipelineCI.pMultisampleState != NULL && 2758ea8349eeee76ae2859c10870fd8bd9e60309eb28Chris Forbes VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO == pipe->graphicsPipelineCI.pMultisampleState->sType) { 2759eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young return pipe->graphicsPipelineCI.pMultisampleState->rasterizationSamples; 2760eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young } 2761eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young return VK_SAMPLE_COUNT_1_BIT; 2762eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young} 2763eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young 2764bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic void list_bits(std::ostream &s, uint32_t bits) { 2765b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes for (int i = 0; i < 32 && bits; i++) { 2766b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes if (bits & (1 << i)) { 2767b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes s << i; 2768b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes bits &= ~(1 << i); 2769b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes if (bits) { 2770b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes s << ","; 2771b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes } 2772b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes } 2773b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes } 2774b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes} 2775b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes 2776eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young// Validate draw-time state related to the PSO 277751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool ValidatePipelineDrawtimeState(layer_data const *dev_data, LAST_BOUND_STATE const &state, const GLOBAL_CB_NODE *pCB, 27784c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis PIPELINE_STATE const *pPipeline) { 2779eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young bool skip_call = false; 278029d196e071b2dc1db47702085469396f2b956820Chris Forbes 2781d79335137b414d5f89284a9ab3e014beb4ada3ebMike Weiblen // Verify vertex binding 278229d196e071b2dc1db47702085469396f2b956820Chris Forbes if (pPipeline->vertexBindingDescriptions.size() > 0) { 278329d196e071b2dc1db47702085469396f2b956820Chris Forbes for (size_t i = 0; i < pPipeline->vertexBindingDescriptions.size(); i++) { 2784312129ec52e6249aa453e27e6be17a8dab1e98b8Tobin Ehlis auto vertex_binding = pPipeline->vertexBindingDescriptions[i].binding; 2785312129ec52e6249aa453e27e6be17a8dab1e98b8Tobin Ehlis if ((pCB->currentDrawData.buffers.size() < (vertex_binding + 1)) || 2786312129ec52e6249aa453e27e6be17a8dab1e98b8Tobin Ehlis (pCB->currentDrawData.buffers[vertex_binding] == VK_NULL_HANDLE)) { 2787cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski skip_call |= 278851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 2789cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski DRAWSTATE_VTX_INDEX_OUT_OF_BOUNDS, "DS", 2790cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "The Pipeline State Object (0x%" PRIxLEAST64 2791cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ") expects that this Command Buffer's vertex binding Index %u " 2792cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "should be set via vkCmdBindVertexBuffers. This is because VkVertexInputBindingDescription struct " 2793cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "at index " PRINTF_SIZE_T_SPECIFIER " of pVertexBindingDescriptions has a binding value of %u.", 2794cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski (uint64_t)state.pipeline_state->pipeline, vertex_binding, i, vertex_binding); 279529d196e071b2dc1db47702085469396f2b956820Chris Forbes } 279629d196e071b2dc1db47702085469396f2b956820Chris Forbes } 279729d196e071b2dc1db47702085469396f2b956820Chris Forbes } else { 279858b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis if (!pCB->currentDrawData.buffers.empty() && !pCB->vertex_buffer_used) { 279951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 28005c288f35b2eab0dab95d18768235fef6ffd69b30Tobin Ehlis 0, __LINE__, DRAWSTATE_VTX_INDEX_OUT_OF_BOUNDS, "DS", 2801226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "Vertex buffers are bound to command buffer (0x%p" 28025c288f35b2eab0dab95d18768235fef6ffd69b30Tobin Ehlis ") but no vertex buffers are attached to this Pipeline State Object (0x%" PRIxLEAST64 ").", 2803226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis pCB->commandBuffer, (uint64_t)state.pipeline_state->pipeline); 280429d196e071b2dc1db47702085469396f2b956820Chris Forbes } 280529d196e071b2dc1db47702085469396f2b956820Chris Forbes } 280629d196e071b2dc1db47702085469396f2b956820Chris Forbes // If Viewport or scissors are dynamic, verify that dynamic count matches PSO count. 280729d196e071b2dc1db47702085469396f2b956820Chris Forbes // Skip check if rasterization is disabled or there is no viewport. 280829d196e071b2dc1db47702085469396f2b956820Chris Forbes if ((!pPipeline->graphicsPipelineCI.pRasterizationState || 280929d196e071b2dc1db47702085469396f2b956820Chris Forbes (pPipeline->graphicsPipelineCI.pRasterizationState->rasterizerDiscardEnable == VK_FALSE)) && 281029d196e071b2dc1db47702085469396f2b956820Chris Forbes pPipeline->graphicsPipelineCI.pViewportState) { 281129d196e071b2dc1db47702085469396f2b956820Chris Forbes bool dynViewport = isDynamic(pPipeline, VK_DYNAMIC_STATE_VIEWPORT); 281229d196e071b2dc1db47702085469396f2b956820Chris Forbes bool dynScissor = isDynamic(pPipeline, VK_DYNAMIC_STATE_SCISSOR); 2813b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes 281429d196e071b2dc1db47702085469396f2b956820Chris Forbes if (dynViewport) { 2815b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes auto requiredViewportsMask = (1 << pPipeline->graphicsPipelineCI.pViewportState->viewportCount) - 1; 2816b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes auto missingViewportMask = ~pCB->viewportMask & requiredViewportsMask; 2817b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes if (missingViewportMask) { 2818b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes std::stringstream ss; 2819b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes ss << "Dynamic viewport(s) "; 2820b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes list_bits(ss, missingViewportMask); 2821d79335137b414d5f89284a9ab3e014beb4ada3ebMike Weiblen ss << " are used by pipeline state object, but were not provided via calls to vkCmdSetViewport()."; 282251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, 2823bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski __LINE__, DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS", "%s", ss.str().c_str()); 282429d196e071b2dc1db47702085469396f2b956820Chris Forbes } 282529d196e071b2dc1db47702085469396f2b956820Chris Forbes } 2826b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes 282729d196e071b2dc1db47702085469396f2b956820Chris Forbes if (dynScissor) { 2828b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes auto requiredScissorMask = (1 << pPipeline->graphicsPipelineCI.pViewportState->scissorCount) - 1; 2829b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes auto missingScissorMask = ~pCB->scissorMask & requiredScissorMask; 2830b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes if (missingScissorMask) { 2831b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes std::stringstream ss; 2832b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes ss << "Dynamic scissor(s) "; 2833b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes list_bits(ss, missingScissorMask); 2834d79335137b414d5f89284a9ab3e014beb4ada3ebMike Weiblen ss << " are used by pipeline state object, but were not provided via calls to vkCmdSetScissor()."; 283551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, 2836bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski __LINE__, DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS", "%s", ss.str().c_str()); 283729d196e071b2dc1db47702085469396f2b956820Chris Forbes } 283829d196e071b2dc1db47702085469396f2b956820Chris Forbes } 283929d196e071b2dc1db47702085469396f2b956820Chris Forbes } 284029d196e071b2dc1db47702085469396f2b956820Chris Forbes 284129d196e071b2dc1db47702085469396f2b956820Chris Forbes // Verify that any MSAA request in PSO matches sample# in bound FB 284229d196e071b2dc1db47702085469396f2b956820Chris Forbes // Skip the check if rasterization is disabled. 284329d196e071b2dc1db47702085469396f2b956820Chris Forbes if (!pPipeline->graphicsPipelineCI.pRasterizationState || 284429d196e071b2dc1db47702085469396f2b956820Chris Forbes (pPipeline->graphicsPipelineCI.pRasterizationState->rasterizerDiscardEnable == VK_FALSE)) { 284529d196e071b2dc1db47702085469396f2b956820Chris Forbes VkSampleCountFlagBits pso_num_samples = getNumSamples(pPipeline); 284629d196e071b2dc1db47702085469396f2b956820Chris Forbes if (pCB->activeRenderPass) { 2847fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes auto const render_pass_info = pCB->activeRenderPass->createInfo.ptr(); 284829d196e071b2dc1db47702085469396f2b956820Chris Forbes const VkSubpassDescription *subpass_desc = &render_pass_info->pSubpasses[pCB->activeSubpass]; 284929d196e071b2dc1db47702085469396f2b956820Chris Forbes uint32_t i; 285076957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes unsigned subpass_num_samples = 0; 28510a7ed0466d3d3c6c71be07d66c200482d9a9d073Chris Forbes 285229d196e071b2dc1db47702085469396f2b956820Chris Forbes for (i = 0; i < subpass_desc->colorAttachmentCount; i++) { 285376957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes auto attachment = subpass_desc->pColorAttachments[i].attachment; 285476957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes if (attachment != VK_ATTACHMENT_UNUSED) 285576957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes subpass_num_samples |= (unsigned)render_pass_info->pAttachments[attachment].samples; 285629d196e071b2dc1db47702085469396f2b956820Chris Forbes } 28570a7ed0466d3d3c6c71be07d66c200482d9a9d073Chris Forbes 285876957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes if (subpass_desc->pDepthStencilAttachment && 285976957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes subpass_desc->pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) { 286076957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes auto attachment = subpass_desc->pDepthStencilAttachment->attachment; 286176957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes subpass_num_samples |= (unsigned)render_pass_info->pAttachments[attachment].samples; 286229d196e071b2dc1db47702085469396f2b956820Chris Forbes } 2863eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young 28640dc3fd4e57b8531638781daa01a2fb5d1048a6fbJamie Madill if (subpass_num_samples && static_cast<unsigned>(pso_num_samples) != subpass_num_samples) { 286529d196e071b2dc1db47702085469396f2b956820Chris Forbes skip_call |= 286651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 2867bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski reinterpret_cast<const uint64_t &>(pPipeline->pipeline), __LINE__, DRAWSTATE_NUM_SAMPLES_MISMATCH, "DS", 2868bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "Num samples mismatch! At draw-time in Pipeline (0x%" PRIxLEAST64 2869bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski ") with %u samples while current RenderPass (0x%" PRIxLEAST64 ") w/ %u samples!", 2870bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski reinterpret_cast<const uint64_t &>(pPipeline->pipeline), pso_num_samples, 2871bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski reinterpret_cast<const uint64_t &>(pCB->activeRenderPass->renderPass), subpass_num_samples); 2872eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young } 287329d196e071b2dc1db47702085469396f2b956820Chris Forbes } else { 287451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 2875bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski reinterpret_cast<const uint64_t &>(pPipeline->pipeline), __LINE__, DRAWSTATE_NUM_SAMPLES_MISMATCH, 2876bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "DS", "No active render pass found at draw-time in Pipeline (0x%" PRIxLEAST64 ")!", 287729d196e071b2dc1db47702085469396f2b956820Chris Forbes reinterpret_cast<const uint64_t &>(pPipeline->pipeline)); 2878eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young } 2879eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young } 2880528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis // Verify that PSO creation renderPass is compatible with active renderPass 2881528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis if (pCB->activeRenderPass) { 2882528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis std::string err_string; 2883a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis if ((pCB->activeRenderPass->renderPass != pPipeline->graphicsPipelineCI.renderPass) && 288451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis !verify_renderpass_compatibility(dev_data, pCB->activeRenderPass->createInfo.ptr(), pPipeline->render_pass_ci.ptr(), 2885528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis err_string)) { 2886528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis // renderPass that PSO was created with must be compatible with active renderPass that PSO is being used with 2887528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis skip_call |= 288851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 2889528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis reinterpret_cast<const uint64_t &>(pPipeline->pipeline), __LINE__, DRAWSTATE_RENDERPASS_INCOMPATIBLE, "DS", 2890cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "At Draw time the active render pass (0x%" PRIxLEAST64 2891cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ") is incompatible w/ gfx pipeline " 2892528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis "(0x%" PRIxLEAST64 ") that was created w/ render pass (0x%" PRIxLEAST64 ") due to: %s", 28936de0e43adfbd3c049252412d998524e7edbd3796Chris Forbes reinterpret_cast<uint64_t &>(pCB->activeRenderPass->renderPass), 28946de0e43adfbd3c049252412d998524e7edbd3796Chris Forbes reinterpret_cast<uint64_t const &>(pPipeline->pipeline), 2895528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis reinterpret_cast<const uint64_t &>(pPipeline->graphicsPipelineCI.renderPass), err_string.c_str()); 2896528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis } 2897c307df2953e6b023531a6ef7fd11e3ee2f2c58b0Chris Forbes 2898c307df2953e6b023531a6ef7fd11e3ee2f2c58b0Chris Forbes if (pPipeline->graphicsPipelineCI.subpass != pCB->activeSubpass) { 2899c307df2953e6b023531a6ef7fd11e3ee2f2c58b0Chris Forbes skip_call |= 290051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 2901c307df2953e6b023531a6ef7fd11e3ee2f2c58b0Chris Forbes reinterpret_cast<uint64_t const &>(pPipeline->pipeline), __LINE__, DRAWSTATE_RENDERPASS_INCOMPATIBLE, "DS", 2902c307df2953e6b023531a6ef7fd11e3ee2f2c58b0Chris Forbes "Pipeline was built for subpass %u but used in subpass %u", pPipeline->graphicsPipelineCI.subpass, 2903c307df2953e6b023531a6ef7fd11e3ee2f2c58b0Chris Forbes pCB->activeSubpass); 2904c307df2953e6b023531a6ef7fd11e3ee2f2c58b0Chris Forbes } 2905528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis } 290629d196e071b2dc1db47702085469396f2b956820Chris Forbes // TODO : Add more checks here 290729d196e071b2dc1db47702085469396f2b956820Chris Forbes 2908eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young return skip_call; 2909eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young} 2910eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young 29115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Validate overall state at the time of a draw call 291251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool ValidateDrawState(layer_data *dev_data, GLOBAL_CB_NODE *cb_node, const bool indexed, 29134f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes const VkPipelineBindPoint bind_point, const char *function, 29144f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes UNIQUE_VALIDATION_ERROR_CODE const msg_code) { 2915e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool result = false; 29161c130ea631a82716dc7334de17767536525f2292Tobin Ehlis auto const &state = cb_node->lastBound[bind_point]; 29174c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis PIPELINE_STATE *pPipe = state.pipeline_state; 291822fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis if (nullptr == pPipe) { 291922fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis result |= log_msg( 292051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 292122fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis DRAWSTATE_INVALID_PIPELINE, "DS", 292222fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis "At Draw/Dispatch time no valid VkPipeline is bound! This is illegal. Please bind one with vkCmdBindPipeline()."); 292322fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis // Early return as any further checks below will be busted w/o a pipeline 2924cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (result) return true; 292522fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis } 29263d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis // First check flag states 29271c130ea631a82716dc7334de17767536525f2292Tobin Ehlis if (VK_PIPELINE_BIND_POINT_GRAPHICS == bind_point) 292851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis result = validate_draw_state_flags(dev_data, cb_node, pPipe, indexed, msg_code); 29297a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis 29305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Now complete other state checks 293169b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis if (VK_NULL_HANDLE != state.pipeline_layout.layout) { 293222fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis string errorString; 293369b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis auto pipeline_layout = pPipe->pipeline_layout; 2934169c4506062f06d6676eb4da3c9e0437d1d9d659Chris Forbes 29351c130ea631a82716dc7334de17767536525f2292Tobin Ehlis for (const auto &set_binding_pair : pPipe->active_slots) { 29361c130ea631a82716dc7334de17767536525f2292Tobin Ehlis uint32_t setIndex = set_binding_pair.first; 293722fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis // If valid set is not bound throw an error 293822fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis if ((state.boundDescriptorSets.size() <= setIndex) || (!state.boundDescriptorSets[setIndex])) { 293951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis result |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 294022fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis DRAWSTATE_DESCRIPTOR_SET_NOT_BOUND, "DS", 2941bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "VkPipeline 0x%" PRIxLEAST64 " uses set #%u but that set is not bound.", 2942bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski (uint64_t)pPipe->pipeline, setIndex); 294351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis } else if (!verify_set_layout_compatibility(dev_data, state.boundDescriptorSets[setIndex], &pipeline_layout, setIndex, 294469b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis errorString)) { 294569b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis // Set is bound but not compatible w/ overlapping pipeline_layout from PSO 294671511c5a10533c910bfe62c3bcf58e2a4054e7acTobin Ehlis VkDescriptorSet setHandle = state.boundDescriptorSets[setIndex]->GetSet(); 294722fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis result |= 294851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, 294922fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis (uint64_t)setHandle, __LINE__, DRAWSTATE_PIPELINE_LAYOUTS_INCOMPATIBLE, "DS", 2950414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller "VkDescriptorSet (0x%" PRIxLEAST64 2951414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller ") bound as set #%u is not compatible with overlapping VkPipelineLayout 0x%" PRIxLEAST64 " due to: %s", 295269b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis reinterpret_cast<uint64_t &>(setHandle), setIndex, reinterpret_cast<uint64_t &>(pipeline_layout.layout), 295369b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis errorString.c_str()); 2954cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else { // Valid set is bound and layout compatible, validate that it's updated 295522fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis // Pull the set node 29561c130ea631a82716dc7334de17767536525f2292Tobin Ehlis cvdescriptorset::DescriptorSet *descriptor_set = state.boundDescriptorSets[setIndex]; 2957aa21bc3b3c5c7adfeb488fc80bdcb339d63615b8Tobin Ehlis // Gather active bindings 2958ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis std::unordered_set<uint32_t> active_bindings; 29591c130ea631a82716dc7334de17767536525f2292Tobin Ehlis for (auto binding : set_binding_pair.second) { 2960ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis active_bindings.insert(binding.first); 2961aa21bc3b3c5c7adfeb488fc80bdcb339d63615b8Tobin Ehlis } 296222fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis // Make sure set has been updated if it has no immutable samplers 296322fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis // If it has immutable samplers, we'll flag error later as needed depending on binding 29641c130ea631a82716dc7334de17767536525f2292Tobin Ehlis if (!descriptor_set->IsUpdated()) { 2965ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis for (auto binding : active_bindings) { 29661c130ea631a82716dc7334de17767536525f2292Tobin Ehlis if (!descriptor_set->GetImmutableSamplerPtrFromBinding(binding)) { 296751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis result |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 2968cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t)descriptor_set->GetSet(), 2969cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, DRAWSTATE_DESCRIPTOR_SET_NOT_UPDATED, "DS", 2970cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Descriptor Set 0x%" PRIxLEAST64 2971cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " bound but was never updated. It is now being used to draw so " 2972cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "this will result in undefined behavior.", 2973cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski (uint64_t)descriptor_set->GetSet()); 2974fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis } 29755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 29765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 29777433ab60c7ff16d37edb0f8b17b606ccd363e210Tobin Ehlis // Validate the draw-time state for this descriptor set 29787433ab60c7ff16d37edb0f8b17b606ccd363e210Tobin Ehlis std::string err_str; 29791c130ea631a82716dc7334de17767536525f2292Tobin Ehlis if (!descriptor_set->ValidateDrawState(set_binding_pair.second, state.dynamicOffsets[setIndex], &err_str)) { 29801c130ea631a82716dc7334de17767536525f2292Tobin Ehlis auto set = descriptor_set->GetSet(); 298151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis result |= log_msg( 298251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, 298351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis reinterpret_cast<const uint64_t &>(set), __LINE__, DRAWSTATE_DESCRIPTOR_SET_NOT_UPDATED, "DS", 298451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis "Descriptor set 0x%" PRIxLEAST64 " encountered the following validation error at %s() time: %s", 298551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis reinterpret_cast<const uint64_t &>(set), function, err_str.c_str()); 29867433ab60c7ff16d37edb0f8b17b606ccd363e210Tobin Ehlis } 29875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 298822fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis } 298922fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis } 2990eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young 2991eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young // Check general pipeline state that needs to be validated at drawtime 299251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (VK_PIPELINE_BIND_POINT_GRAPHICS == bind_point) result |= ValidatePipelineDrawtimeState(dev_data, state, cb_node, pPipe); 2993eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young 29945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 29955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 29965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 299751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic void UpdateDrawState(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, const VkPipelineBindPoint bind_point) { 29981c130ea631a82716dc7334de17767536525f2292Tobin Ehlis auto const &state = cb_state->lastBound[bind_point]; 2999ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis PIPELINE_STATE *pPipe = state.pipeline_state; 3000ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis if (VK_NULL_HANDLE != state.pipeline_layout.layout) { 30011c130ea631a82716dc7334de17767536525f2292Tobin Ehlis for (const auto &set_binding_pair : pPipe->active_slots) { 30021c130ea631a82716dc7334de17767536525f2292Tobin Ehlis uint32_t setIndex = set_binding_pair.first; 3003ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis // Pull the set node 30041c130ea631a82716dc7334de17767536525f2292Tobin Ehlis cvdescriptorset::DescriptorSet *descriptor_set = state.boundDescriptorSets[setIndex]; 3005ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis // Bind this set and its active descriptor resources to the command buffer 30061c130ea631a82716dc7334de17767536525f2292Tobin Ehlis descriptor_set->BindCommandBuffer(cb_state, set_binding_pair.second); 30077433ab60c7ff16d37edb0f8b17b606ccd363e210Tobin Ehlis // For given active slots record updated images & buffers 30081c130ea631a82716dc7334de17767536525f2292Tobin Ehlis descriptor_set->GetStorageUpdates(set_binding_pair.second, &cb_state->updateBuffers, &cb_state->updateImages); 3009ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis } 3010ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis } 301158b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis if (pPipe->vertexBindingDescriptions.size() > 0) { 301258b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis cb_state->vertex_buffer_used = true; 301358b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis } 3014ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis} 3015ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis 3016a27508babf63d50aea75883a3702979193c23683Mark Young// Validate HW line width capabilities prior to setting requested line width. 301751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool verifyLineWidth(layer_data *dev_data, DRAW_STATE_ERROR dsError, const uint64_t &target, float lineWidth) { 3018a27508babf63d50aea75883a3702979193c23683Mark Young bool skip_call = false; 3019a27508babf63d50aea75883a3702979193c23683Mark Young 3020a27508babf63d50aea75883a3702979193c23683Mark Young // First check to see if the physical device supports wide lines. 302151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if ((VK_FALSE == dev_data->enabled_features.wideLines) && (1.0f != lineWidth)) { 302251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, target, __LINE__, 3023cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski dsError, "DS", 3024cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Attempt to set lineWidth to %f but physical device wideLines feature " 3025cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "not supported/enabled so lineWidth must be 1.0f!", 3026a27508babf63d50aea75883a3702979193c23683Mark Young lineWidth); 3027a27508babf63d50aea75883a3702979193c23683Mark Young } else { 3028a27508babf63d50aea75883a3702979193c23683Mark Young // Otherwise, make sure the width falls in the valid range. 302951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if ((dev_data->phys_dev_properties.properties.limits.lineWidthRange[0] > lineWidth) || 303051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis (dev_data->phys_dev_properties.properties.limits.lineWidthRange[1] < lineWidth)) { 303151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, target, 3032cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, dsError, "DS", 3033cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Attempt to set lineWidth to %f but physical device limits line width " 3034cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "to between [%f, %f]!", 303551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis lineWidth, dev_data->phys_dev_properties.properties.limits.lineWidthRange[0], 303651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->phys_dev_properties.properties.limits.lineWidthRange[1]); 3037a27508babf63d50aea75883a3702979193c23683Mark Young } 3038a27508babf63d50aea75883a3702979193c23683Mark Young } 3039a27508babf63d50aea75883a3702979193c23683Mark Young 3040a27508babf63d50aea75883a3702979193c23683Mark Young return skip_call; 3041a27508babf63d50aea75883a3702979193c23683Mark Young} 3042a27508babf63d50aea75883a3702979193c23683Mark Young 30435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Verify that create state for a pipeline is valid 304451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool verifyPipelineCreateState(layer_data *dev_data, std::vector<PIPELINE_STATE *> pPipelines, int pipelineIndex) { 304583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 30465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 30474c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis PIPELINE_STATE *pPipeline = pPipelines[pipelineIndex]; 30485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 30495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // If create derivative bit is set, check that we've specified a base 30505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // pipeline correctly, and that the base pipeline was created to allow 30515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // derivatives. 30525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pPipeline->graphicsPipelineCI.flags & VK_PIPELINE_CREATE_DERIVATIVE_BIT) { 30534c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis PIPELINE_STATE *pBasePipeline = nullptr; 30545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!((pPipeline->graphicsPipelineCI.basePipelineHandle != VK_NULL_HANDLE) ^ 30555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (pPipeline->graphicsPipelineCI.basePipelineIndex != -1))) { 3056f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt // This check is a superset of VALIDATION_ERROR_00526 and VALIDATION_ERROR_00528 305751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 305883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS", 305983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis "Invalid Pipeline CreateInfo: exactly one of base pipeline index and handle must be specified"); 30605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (pPipeline->graphicsPipelineCI.basePipelineIndex != -1) { 30615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pPipeline->graphicsPipelineCI.basePipelineIndex >= pipelineIndex) { 306283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= 306351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 3064f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt VALIDATION_ERROR_00518, "DS", 3065f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt "Invalid Pipeline CreateInfo: base pipeline must occur earlier in array than derivative pipeline. %s", 3066f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt validation_error_map[VALIDATION_ERROR_00518]); 30675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 30685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pBasePipeline = pPipelines[pPipeline->graphicsPipelineCI.basePipelineIndex]; 30695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 30705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (pPipeline->graphicsPipelineCI.basePipelineHandle != VK_NULL_HANDLE) { 307151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis pBasePipeline = getPipelineState(dev_data, pPipeline->graphicsPipelineCI.basePipelineHandle); 30725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 30735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 30745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pBasePipeline && !(pBasePipeline->graphicsPipelineCI.flags & VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT)) { 307551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 307683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS", 307783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis "Invalid Pipeline CreateInfo: base pipeline does not allow derivatives."); 30785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 30795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 30805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 30815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pPipeline->graphicsPipelineCI.pColorBlendState != NULL) { 3082fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis const safe_VkPipelineColorBlendStateCreateInfo *color_blend_state = pPipeline->graphicsPipelineCI.pColorBlendState; 30839a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto const render_pass_info = GetRenderPassState(dev_data, pPipeline->graphicsPipelineCI.renderPass)->createInfo.ptr(); 3084fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis const VkSubpassDescription *subpass_desc = &render_pass_info->pSubpasses[pPipeline->graphicsPipelineCI.subpass]; 3085fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis if (color_blend_state->attachmentCount != subpass_desc->colorAttachmentCount) { 3086fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis skip_call |= log_msg( 308751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 3088fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis reinterpret_cast<const uint64_t &>(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_02109, "DS", 3089fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis "vkCreateGraphicsPipelines(): Render pass (0x%" PRIxLEAST64 3090fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis ") subpass %u has colorAttachmentCount of %u which doesn't match the pColorBlendState->attachmentCount of %u. %s", 3091fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis reinterpret_cast<const uint64_t &>(pPipeline->graphicsPipelineCI.renderPass), pPipeline->graphicsPipelineCI.subpass, 3092fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis subpass_desc->colorAttachmentCount, color_blend_state->attachmentCount, 3093fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis validation_error_map[VALIDATION_ERROR_02109]); 3094fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis } 309551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (!dev_data->enabled_features.independentBlend) { 30963d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis if (pPipeline->attachments.size() > 1) { 309726c548826ff0f83d12c769b51e7d6f76d1265c0eChris Forbes VkPipelineColorBlendAttachmentState *pAttachments = &pPipeline->attachments[0]; 3098c7bd67f06427b08ba65cdf2dd529c8234beebdd5Mark Lobodzinski for (size_t i = 1; i < pPipeline->attachments.size(); i++) { 309906811df0256552cd7da9d7297672af377463fc4aMark Mueller // Quoting the spec: "If [the independent blend] feature is not enabled, the VkPipelineColorBlendAttachmentState 310006811df0256552cd7da9d7297672af377463fc4aMark Mueller // settings for all color attachments must be identical." VkPipelineColorBlendAttachmentState contains 310106811df0256552cd7da9d7297672af377463fc4aMark Mueller // only attachment state, so memcmp is best suited for the comparison 310206811df0256552cd7da9d7297672af377463fc4aMark Mueller if (memcmp(static_cast<const void *>(pAttachments), static_cast<const void *>(&pAttachments[i]), 310306811df0256552cd7da9d7297672af377463fc4aMark Mueller sizeof(pAttachments[0]))) { 310451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 3105cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, VALIDATION_ERROR_01532, "DS", 3106cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Invalid Pipeline CreateInfo: If independent blend feature not " 3107cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "enabled, all elements of pAttachments must be identical. %s", 3108cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski validation_error_map[VALIDATION_ERROR_01532]); 310906811df0256552cd7da9d7297672af377463fc4aMark Mueller break; 3110c7bd67f06427b08ba65cdf2dd529c8234beebdd5Mark Lobodzinski } 31115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 31125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 31135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 311451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (!dev_data->enabled_features.logicOp && (pPipeline->graphicsPipelineCI.pColorBlendState->logicOpEnable != VK_FALSE)) { 311583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= 311651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 3117f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt VALIDATION_ERROR_01533, "DS", 3118f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt "Invalid Pipeline CreateInfo: If logic operations feature not enabled, logicOpEnable must be VK_FALSE. %s", 3119f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt validation_error_map[VALIDATION_ERROR_01533]); 31205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 31215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 31225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3123a61b537fcb6a4f7b92cd217b3964ad7a48109da1Tobin Ehlis // Ensure the subpass index is valid. If not, then validate_and_capture_pipeline_shader_state 31245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // produces nonsense errors that confuse users. Other layers should already 31255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // emit errors for renderpass being invalid. 31269a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto renderPass = GetRenderPassState(dev_data, pPipeline->graphicsPipelineCI.renderPass); 3127fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes if (renderPass && pPipeline->graphicsPipelineCI.subpass >= renderPass->createInfo.subpassCount) { 312851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 3129cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VALIDATION_ERROR_02122, "DS", 3130cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Invalid Pipeline CreateInfo State: Subpass index %u " 3131cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "is out of range for this renderpass (0..%u). %s", 3132f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt pPipeline->graphicsPipelineCI.subpass, renderPass->createInfo.subpassCount - 1, 3133f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt validation_error_map[VALIDATION_ERROR_02122]); 31345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 31355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 313651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (!GetDisables(dev_data)->shader_validation && 313751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis !validate_and_capture_pipeline_shader_state(dev_data->report_data, pPipeline, &dev_data->enabled_features, 313851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->shaderModuleMap)) { 313983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call = true; 31405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 314152156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes // Each shader's stage must be unique 314252156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes if (pPipeline->duplicate_shaders) { 314352156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes for (uint32_t stage = VK_SHADER_STAGE_VERTEX_BIT; stage & VK_SHADER_STAGE_ALL_GRAPHICS; stage <<= 1) { 314452156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes if (pPipeline->duplicate_shaders & stage) { 314551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, 314683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis __LINE__, DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS", 314783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis "Invalid Pipeline CreateInfo State: Multiple shaders provided for stage %s", 314883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis string_VkShaderStageFlagBits(VkShaderStageFlagBits(stage))); 314952156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes } 315052156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes } 315152156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes } 31525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // VS is required 31535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!(pPipeline->active_shaders & VK_SHADER_STAGE_VERTEX_BIT)) { 315451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 3155f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt VALIDATION_ERROR_00532, "DS", "Invalid Pipeline CreateInfo State: Vertex Shader required. %s", 3156f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt validation_error_map[VALIDATION_ERROR_00532]); 31575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 31585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Either both or neither TC/TE shaders should be defined 3159f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt if ((pPipeline->active_shaders & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) && 3160f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt !(pPipeline->active_shaders & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)) { 316151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 3162f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt VALIDATION_ERROR_00534, "DS", 3163f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt "Invalid Pipeline CreateInfo State: TE and TC shaders must be included or excluded as a pair. %s", 3164f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt validation_error_map[VALIDATION_ERROR_00534]); 3165f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt } 3166f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt if (!(pPipeline->active_shaders & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) && 3167f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt (pPipeline->active_shaders & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)) { 316851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 3169f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt VALIDATION_ERROR_00535, "DS", 3170f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt "Invalid Pipeline CreateInfo State: TE and TC shaders must be included or excluded as a pair. %s", 3171f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt validation_error_map[VALIDATION_ERROR_00535]); 31725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 31735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Compute shaders should be specified independent of Gfx shaders 3174f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt if (pPipeline->active_shaders & VK_SHADER_STAGE_COMPUTE_BIT) { 317551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 3176f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt VALIDATION_ERROR_00533, "DS", 3177f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt "Invalid Pipeline CreateInfo State: Do not specify Compute Shader for Gfx Pipeline. %s", 3178f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt validation_error_map[VALIDATION_ERROR_00533]); 31795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 31805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // VK_PRIMITIVE_TOPOLOGY_PATCH_LIST primitive topology is only valid for tessellation pipelines. 31815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Mismatching primitive topology and tessellation fails graphics pipeline creation. 31825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pPipeline->active_shaders & (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) && 3183ca546210846c65808717f8875deae39bd227c240Tobin Ehlis (!pPipeline->graphicsPipelineCI.pInputAssemblyState || 3184ca546210846c65808717f8875deae39bd227c240Tobin Ehlis pPipeline->graphicsPipelineCI.pInputAssemblyState->topology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST)) { 318551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 3186cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VALIDATION_ERROR_02099, "DS", 3187cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Invalid Pipeline CreateInfo State: " 3188cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "VK_PRIMITIVE_TOPOLOGY_PATCH_LIST must be set as IA " 3189cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "topology for tessellation pipelines. %s", 3190f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt validation_error_map[VALIDATION_ERROR_02099]); 31915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 3192ca546210846c65808717f8875deae39bd227c240Tobin Ehlis if (pPipeline->graphicsPipelineCI.pInputAssemblyState && 3193ca546210846c65808717f8875deae39bd227c240Tobin Ehlis pPipeline->graphicsPipelineCI.pInputAssemblyState->topology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST) { 31945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (~pPipeline->active_shaders & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) { 319551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 3196cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VALIDATION_ERROR_02100, "DS", 3197cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Invalid Pipeline CreateInfo State: " 3198cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "VK_PRIMITIVE_TOPOLOGY_PATCH_LIST primitive " 3199cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "topology is only valid for tessellation pipelines. %s", 3200f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt validation_error_map[VALIDATION_ERROR_02100]); 32015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 32025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 3203f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt 3204f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt if (pPipeline->graphicsPipelineCI.pTessellationState && 3205f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt ((pPipeline->graphicsPipelineCI.pTessellationState->patchControlPoints == 0) || 3206f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt (pPipeline->graphicsPipelineCI.pTessellationState->patchControlPoints > 320751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->phys_dev_properties.properties.limits.maxTessellationPatchSize))) { 320851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 3209cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VALIDATION_ERROR_01426, "DS", 3210cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Invalid Pipeline CreateInfo State: " 3211cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "VK_PRIMITIVE_TOPOLOGY_PATCH_LIST primitive " 3212cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "topology used with patchControlPoints value %u." 3213cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " patchControlPoints should be >0 and <=%u. %s", 3214f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt pPipeline->graphicsPipelineCI.pTessellationState->patchControlPoints, 321551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->phys_dev_properties.properties.limits.maxTessellationPatchSize, 3216f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt validation_error_map[VALIDATION_ERROR_01426]); 3217f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt } 3218f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt 32196b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen // If a rasterization state is provided... 3220a27508babf63d50aea75883a3702979193c23683Mark Young if (pPipeline->graphicsPipelineCI.pRasterizationState) { 32216b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen 32226b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen // Make sure that the line width conforms to the HW. 3223a27508babf63d50aea75883a3702979193c23683Mark Young if (!isDynamic(pPipeline, VK_DYNAMIC_STATE_LINE_WIDTH)) { 322451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call |= verifyLineWidth(dev_data, DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, 32256de0e43adfbd3c049252412d998524e7edbd3796Chris Forbes reinterpret_cast<uint64_t const &>(pPipeline->pipeline), 322683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis pPipeline->graphicsPipelineCI.pRasterizationState->lineWidth); 3227a27508babf63d50aea75883a3702979193c23683Mark Young } 32285dcdd90e54199dfeb29938a3a03d998397c22664Chris Forbes 32296b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen // If rasterization is enabled... 32306b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen if (pPipeline->graphicsPipelineCI.pRasterizationState->rasterizerDiscardEnable == VK_FALSE) { 32316b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen auto subpass_desc = renderPass ? &renderPass->createInfo.pSubpasses[pPipeline->graphicsPipelineCI.subpass] : nullptr; 32326b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen 32336b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen // If subpass uses a depth/stencil attachment, pDepthStencilState must be a pointer to a valid structure 32346b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen if (subpass_desc && subpass_desc->pDepthStencilAttachment && 32356b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen subpass_desc->pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) { 32366b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen if (!pPipeline->graphicsPipelineCI.pDepthStencilState) { 32376b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 32386b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, VALIDATION_ERROR_02115, "DS", 32396b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen "Invalid Pipeline CreateInfo State: pDepthStencilState is NULL when rasterization is " 32406b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen "enabled and subpass uses a depth/stencil attachment. %s", 32416b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen validation_error_map[VALIDATION_ERROR_02115]); 32426b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen } 32435dcdd90e54199dfeb29938a3a03d998397c22664Chris Forbes } 3244326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen 3245326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen // If subpass uses color attachments, pColorBlendState must be valid pointer 3246326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen if (subpass_desc) { 3247326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen uint32_t color_attachment_count = 0; 3248326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen for (uint32_t i = 0; i < subpass_desc->colorAttachmentCount; ++i) { 3249326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen if (subpass_desc->pColorAttachments[i].attachment != VK_ATTACHMENT_UNUSED) { 3250326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen ++color_attachment_count; 3251326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen } 3252326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen } 3253326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen if (color_attachment_count > 0 && pPipeline->graphicsPipelineCI.pColorBlendState == nullptr) { 3254326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 3255326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, VALIDATION_ERROR_02116, "DS", 3256326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen "Invalid Pipeline CreateInfo State: pColorBlendState is NULL when rasterization is " 3257326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen "enabled and subpass uses color attachments. %s", 3258326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen validation_error_map[VALIDATION_ERROR_02116]); 3259326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen } 3260326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen } 32615dcdd90e54199dfeb29938a3a03d998397c22664Chris Forbes } 32625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 32636b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen 326483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis return skip_call; 32655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 32665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 32675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Free the Pipeline nodes 326851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic void deletePipelines(layer_data *dev_data) { 326951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (dev_data->pipelineMap.size() <= 0) return; 327051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis for (auto &pipe_map_pair : dev_data->pipelineMap) { 3271ca546210846c65808717f8875deae39bd227c240Tobin Ehlis delete pipe_map_pair.second; 32725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 327351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->pipelineMap.clear(); 32745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 32755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 32765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Block of code at start here specifically for managing/tracking DSs 32775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 32785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Return Pool node ptr for specified pool or else NULL 32799a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisDESCRIPTOR_POOL_STATE *GetDescriptorPoolState(const layer_data *dev_data, const VkDescriptorPool pool) { 3280bb7ea477706f90eb2a72887f652795bc79f60ddeTobin Ehlis auto pool_it = dev_data->descriptorPoolMap.find(pool); 3281bb7ea477706f90eb2a72887f652795bc79f60ddeTobin Ehlis if (pool_it == dev_data->descriptorPoolMap.end()) { 32825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return NULL; 32835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 3284bb7ea477706f90eb2a72887f652795bc79f60ddeTobin Ehlis return pool_it->second; 32855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 32865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 32875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Validate that given set is valid and that it's not being used by an in-flight CmdBuffer 32885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// func_str is the name of the calling function 3289e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves// Return false if no errors occur 3290e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves// Return true if validation error occurs and callback returns true (to skip upcoming API call down the chain) 32910dcd0f7b37456e2e552d37094ba503c0d089b906Tobin Ehlisstatic bool validateIdleDescriptorSet(const layer_data *dev_data, VkDescriptorSet set, std::string func_str) { 3292cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.idle_descriptor_set) return false; 3293e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool skip_call = false; 32940dcd0f7b37456e2e552d37094ba503c0d089b906Tobin Ehlis auto set_node = dev_data->setMap.find(set); 32950dcd0f7b37456e2e552d37094ba503c0d089b906Tobin Ehlis if (set_node == dev_data->setMap.end()) { 32960dcd0f7b37456e2e552d37094ba503c0d089b906Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, 32975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (uint64_t)(set), __LINE__, DRAWSTATE_DOUBLE_DESTROY, "DS", 3298414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller "Cannot call %s() on descriptor set 0x%" PRIxLEAST64 " that has not been allocated.", func_str.c_str(), 32995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (uint64_t)(set)); 33005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 33011c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis // TODO : This covers various error cases so should pass error enum into this function and use passed in enum here 33025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (set_node->second->in_use.load()) { 33031c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis skip_call |= 33040dcd0f7b37456e2e552d37094ba503c0d089b906Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, 33051c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis (uint64_t)(set), __LINE__, VALIDATION_ERROR_00919, "DS", 33061c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis "Cannot call %s() on descriptor set 0x%" PRIxLEAST64 " that is in use by a command buffer. %s", 33071c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis func_str.c_str(), (uint64_t)(set), validation_error_map[VALIDATION_ERROR_00919]); 33085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 33095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 33105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return skip_call; 33115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 3312f80bf38f4fb3f177b3e1be11b7b1c5edcdbf7d9bChris Forbes 3313e6651096ed8f07840447783c66827cc16d659a49Tobin Ehlis// Remove set from setMap and delete the set 33149dd448578d59cb5ce692e833ba230783b30f3550Tobin Ehlisstatic void freeDescriptorSet(layer_data *dev_data, cvdescriptorset::DescriptorSet *descriptor_set) { 33159dd448578d59cb5ce692e833ba230783b30f3550Tobin Ehlis dev_data->setMap.erase(descriptor_set->GetSet()); 33169dd448578d59cb5ce692e833ba230783b30f3550Tobin Ehlis delete descriptor_set; 33179dd448578d59cb5ce692e833ba230783b30f3550Tobin Ehlis} 33185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Free all DS Pools including their Sets & related sub-structs 33195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// NOTE : Calls to this function should be wrapped in mutex 332051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic void deletePools(layer_data *dev_data) { 332151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (dev_data->descriptorPoolMap.size() <= 0) return; 332251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis for (auto ii = dev_data->descriptorPoolMap.begin(); ii != dev_data->descriptorPoolMap.end(); ++ii) { 3323c5f47f0a54e14c47d402aeabc6498d981ecda9ccTobin Ehlis // Remove this pools' sets from setMap and delete them 3324cb9ce9e05b8e939d3da35c64997c70049877f4feTobin Ehlis for (auto ds : (*ii).second->sets) { 332551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis freeDescriptorSet(dev_data, ds); 33265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 3327f13bee0887f3c3d1d597c82869864be3be836737Tobin Ehlis (*ii).second->sets.clear(); 33285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 332951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->descriptorPoolMap.clear(); 33305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 33315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 333251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic void clearDescriptorPool(layer_data *dev_data, const VkDevice device, const VkDescriptorPool pool, 33335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkDescriptorPoolResetFlags flags) { 33349a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DESCRIPTOR_POOL_STATE *pPool = GetDescriptorPoolState(dev_data, pool); 3335de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis // TODO: validate flags 3336de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis // For every set off of this pool, clear it, remove from setMap, and free cvdescriptorset::DescriptorSet 3337de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis for (auto ds : pPool->sets) { 333851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis freeDescriptorSet(dev_data, ds); 3339de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis } 3340de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis pPool->sets.clear(); 3341de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis // Reset available count for each type and available sets for this pool 3342de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis for (uint32_t i = 0; i < pPool->availableDescriptorTypeCount.size(); ++i) { 3343de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis pPool->availableDescriptorTypeCount[i] = pPool->maxDescriptorTypeCount[i]; 33445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 3345de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis pPool->availableSets = pPool->maxSets; 33465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 33475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 33485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// For given CB object, fetch associated CB Node from map 33499a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisGLOBAL_CB_NODE *GetCBNode(layer_data const *dev_data, const VkCommandBuffer cb) { 335051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis auto it = dev_data->commandBufferMap.find(cb); 335151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (it == dev_data->commandBufferMap.end()) { 33525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return NULL; 33535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 33545121a8dcacb23766ba4455b4eea429f0a3d62099Chris Forbes return it->second; 33555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 33565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Free all CB Nodes 33575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// NOTE : Calls to this function should be wrapped in mutex 335851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic void deleteCommandBuffers(layer_data *dev_data) { 335951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (dev_data->commandBufferMap.empty()) { 33605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return; 33615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 336251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis for (auto ii = dev_data->commandBufferMap.begin(); ii != dev_data->commandBufferMap.end(); ++ii) { 33635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis delete (*ii).second; 33645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 336551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->commandBufferMap.clear(); 33665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 33675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3368e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool report_error_no_cb_begin(const layer_data *dev_data, const VkCommandBuffer cb, const char *caller_name) { 33695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 33705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (uint64_t)cb, __LINE__, DRAWSTATE_NO_BEGIN_COMMAND_BUFFER, "DS", 33715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis "You must call vkBeginCommandBuffer() before this call to %s", caller_name); 33725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 33735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 337429f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis// If a renderpass is active, verify that the given command type is appropriate for current subpass state 337529f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlisbool ValidateCmdSubpassState(const layer_data *dev_data, const GLOBAL_CB_NODE *pCB, const CMD_TYPE cmd_type) { 3376cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!pCB->activeRenderPass) return false; 3377e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool skip_call = false; 3378d0d8e333806eaac08bdc87ddeff886dc2b0f09e7Tobin Ehlis if (pCB->activeSubpassContents == VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS && 3379d0d8e333806eaac08bdc87ddeff886dc2b0f09e7Tobin Ehlis (cmd_type != CMD_EXECUTECOMMANDS && cmd_type != CMD_NEXTSUBPASS && cmd_type != CMD_ENDRENDERPASS)) { 33805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 33815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis DRAWSTATE_INVALID_COMMAND_BUFFER, "DS", 33825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis "Commands cannot be called in a subpass using secondary command buffers."); 33835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (pCB->activeSubpassContents == VK_SUBPASS_CONTENTS_INLINE && cmd_type == CMD_EXECUTECOMMANDS) { 33845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 33855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis DRAWSTATE_INVALID_COMMAND_BUFFER, "DS", 33865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis "vkCmdExecuteCommands() cannot be called in a subpass using inline commands."); 33875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 33885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return skip_call; 33895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 33905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 339151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool checkGraphicsBit(const layer_data *dev_data, VkQueueFlags flags, const char *name) { 33925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!(flags & VK_QUEUE_GRAPHICS_BIT)) 339351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis return log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 33945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis DRAWSTATE_INVALID_COMMAND_BUFFER, "DS", 33955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis "Cannot call %s on a command buffer allocated from a pool without graphics capabilities.", name); 33965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 33975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 33985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 339951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool checkComputeBit(const layer_data *dev_data, VkQueueFlags flags, const char *name) { 34005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!(flags & VK_QUEUE_COMPUTE_BIT)) 340151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis return log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 34025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis DRAWSTATE_INVALID_COMMAND_BUFFER, "DS", 34035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis "Cannot call %s on a command buffer allocated from a pool without compute capabilities.", name); 34045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 34055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 34065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 340751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool checkGraphicsOrComputeBit(const layer_data *dev_data, VkQueueFlags flags, const char *name) { 34085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!((flags & VK_QUEUE_GRAPHICS_BIT) || (flags & VK_QUEUE_COMPUTE_BIT))) 340951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis return log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 34105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis DRAWSTATE_INVALID_COMMAND_BUFFER, "DS", 34115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis "Cannot call %s on a command buffer allocated from a pool without graphics capabilities.", name); 34125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 34135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 34145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3415623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski// Validate the given command being added to the specified cmd buffer, flagging errors if CB is not in the recording state or if 3416623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski// there's an issue with the Cmd ordering 341751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisbool ValidateCmd(layer_data *dev_data, GLOBAL_CB_NODE *pCB, const CMD_TYPE cmd, const char *caller_name) { 341883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 34199a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pPool = GetCommandPoolNode(dev_data, pCB->createInfo.commandPool); 3420a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes if (pPool) { 342151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis VkQueueFlags flags = dev_data->phys_dev_properties.queue_family_properties[pPool->queueFamilyIndex].queueFlags; 34225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis switch (cmd) { 3423cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_BINDPIPELINE: 3424cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_BINDPIPELINEDELTA: 3425cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_BINDDESCRIPTORSETS: 3426cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_FILLBUFFER: 3427cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_CLEARCOLORIMAGE: 3428cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETEVENT: 3429cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_RESETEVENT: 3430cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_WAITEVENTS: 3431cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_BEGINQUERY: 3432cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_ENDQUERY: 3433cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_RESETQUERYPOOL: 3434cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_COPYQUERYPOOLRESULTS: 3435cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_WRITETIMESTAMP: 343651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call |= checkGraphicsOrComputeBit(dev_data, flags, cmdTypeToString(cmd).c_str()); 3437cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3438cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETVIEWPORTSTATE: 3439cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETSCISSORSTATE: 3440cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETLINEWIDTHSTATE: 3441cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETDEPTHBIASSTATE: 3442cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETBLENDSTATE: 3443cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETDEPTHBOUNDSSTATE: 3444cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETSTENCILREADMASKSTATE: 3445cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETSTENCILWRITEMASKSTATE: 3446cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETSTENCILREFERENCESTATE: 3447cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_BINDINDEXBUFFER: 3448cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_BINDVERTEXBUFFER: 3449cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_DRAW: 3450cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_DRAWINDEXED: 3451cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_DRAWINDIRECT: 3452cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_DRAWINDEXEDINDIRECT: 3453cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_BLITIMAGE: 3454cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_CLEARATTACHMENTS: 3455cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_CLEARDEPTHSTENCILIMAGE: 3456cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_RESOLVEIMAGE: 3457cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_BEGINRENDERPASS: 3458cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_NEXTSUBPASS: 3459cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_ENDRENDERPASS: 346051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call |= checkGraphicsBit(dev_data, flags, cmdTypeToString(cmd).c_str()); 3461cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3462cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_DISPATCH: 3463cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_DISPATCHINDIRECT: 346451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call |= checkComputeBit(dev_data, flags, cmdTypeToString(cmd).c_str()); 3465cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3466cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_COPYBUFFER: 3467cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_COPYIMAGE: 3468cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_COPYBUFFERTOIMAGE: 3469cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_COPYIMAGETOBUFFER: 3470cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_CLONEIMAGEDATA: 3471cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_UPDATEBUFFER: 3472cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_PIPELINEBARRIER: 3473cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_EXECUTECOMMANDS: 3474cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_END: 3475cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3476cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 3477cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 34785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 34795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 34805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB->state != CB_RECORDING) { 348151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call |= report_error_no_cb_begin(dev_data, pCB->commandBuffer, caller_name); 34827651c2eb9fe152ba62921ed60454afd882357e2aTobin Ehlis } else { 348351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call |= ValidateCmdSubpassState(dev_data, pCB, cmd); 34845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 348583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis return skip_call; 34865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 348729f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis 34881ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlisvoid UpdateCmdBufferLastCmd(GLOBAL_CB_NODE *cb_state, const CMD_TYPE cmd) { 348929f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis if (cb_state->state == CB_RECORDING) { 349029f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis cb_state->last_cmd = cmd; 349129f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis } 349229f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis} 34937e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis// For given object struct return a ptr of BASE_NODE type for its wrapping struct 34947e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin EhlisBASE_NODE *GetStateStructPtrFromObject(layer_data *dev_data, VK_OBJECT object_struct) { 34957e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis BASE_NODE *base_ptr = nullptr; 34967e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis switch (object_struct.type) { 3497cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT: { 34989a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetSetNode(dev_data, reinterpret_cast<VkDescriptorSet &>(object_struct.handle)); 3499cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3500cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3501cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT: { 35029a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetSamplerState(dev_data, reinterpret_cast<VkSampler &>(object_struct.handle)); 3503cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3504cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3505cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT: { 35069a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetQueryPoolNode(dev_data, reinterpret_cast<VkQueryPool &>(object_struct.handle)); 3507cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3508cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3509cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT: { 3510cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski base_ptr = getPipelineState(dev_data, reinterpret_cast<VkPipeline &>(object_struct.handle)); 3511cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3512cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3513cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT: { 35149a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetBufferState(dev_data, reinterpret_cast<VkBuffer &>(object_struct.handle)); 3515cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3516cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3517cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT: { 35189a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetBufferViewState(dev_data, reinterpret_cast<VkBufferView &>(object_struct.handle)); 3519cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3520cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3521cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT: { 35229a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetImageState(dev_data, reinterpret_cast<VkImage &>(object_struct.handle)); 3523cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3524cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3525cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT: { 35269a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetImageViewState(dev_data, reinterpret_cast<VkImageView &>(object_struct.handle)); 3527cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3528cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3529cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT: { 35309a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetEventNode(dev_data, reinterpret_cast<VkEvent &>(object_struct.handle)); 3531cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3532cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3533cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT: { 35349a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetDescriptorPoolState(dev_data, reinterpret_cast<VkDescriptorPool &>(object_struct.handle)); 3535cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3536cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3537cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT: { 35389a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetCommandPoolNode(dev_data, reinterpret_cast<VkCommandPool &>(object_struct.handle)); 3539cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3540cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3541cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT: { 35429a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetFramebufferState(dev_data, reinterpret_cast<VkFramebuffer &>(object_struct.handle)); 3543cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3544cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3545cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT: { 35469a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetRenderPassState(dev_data, reinterpret_cast<VkRenderPass &>(object_struct.handle)); 3547cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3548cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3549cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT: { 35509a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetMemObjInfo(dev_data, reinterpret_cast<VkDeviceMemory &>(object_struct.handle)); 3551cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3552cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3553cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 3554cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // TODO : Any other objects to be handled here? 3555cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski assert(0); 3556cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3557bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis } 35587e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis return base_ptr; 35597e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis} 35607e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis 35617e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis// Tie the VK_OBJECT to the cmd buffer which includes: 35627e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis// Add object_binding to cmd buffer 35637e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis// Add cb_binding to object 35647e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlisstatic void addCommandBufferBinding(std::unordered_set<GLOBAL_CB_NODE *> *cb_bindings, VK_OBJECT obj, GLOBAL_CB_NODE *cb_node) { 35657e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis cb_bindings->insert(cb_node); 35667e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis cb_node->object_bindings.insert(obj); 35677e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis} 35687e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis// For a given object, if cb_node is in that objects cb_bindings, remove cb_node 35697e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlisstatic void removeCommandBufferBinding(layer_data *dev_data, VK_OBJECT const *object, GLOBAL_CB_NODE *cb_node) { 35707e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis BASE_NODE *base_obj = GetStateStructPtrFromObject(dev_data, *object); 3571cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (base_obj) base_obj->cb_bindings.erase(cb_node); 3572bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis} 35735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Reset the command buffer state 35745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Maintain the createInfo and set state to CB_NEW, but clear all other state 3575400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlisstatic void resetCB(layer_data *dev_data, const VkCommandBuffer cb) { 3576400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis GLOBAL_CB_NODE *pCB = dev_data->commandBufferMap[cb]; 35775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 3578b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine pCB->in_use.store(0); 3579347d4d3139a1e743ed85bd375c20fd35bbe68d74Chris Forbes pCB->last_cmd = CMD_NONE; 35805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Reset CB state (note that createInfo is not cleared) 35815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->commandBuffer = cb; 35825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis memset(&pCB->beginInfo, 0, sizeof(VkCommandBufferBeginInfo)); 35835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis memset(&pCB->inheritanceInfo, 0, sizeof(VkCommandBufferInheritanceInfo)); 35845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->numCmds = 0; 35855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis memset(pCB->drawCount, 0, NUM_DRAW_TYPES * sizeof(uint64_t)); 35865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->state = CB_NEW; 35875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->submitCount = 0; 35885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->status = 0; 3589b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes pCB->viewportMask = 0; 3590b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes pCB->scissorMask = 0; 359193c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski 359272d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis for (uint32_t i = 0; i < VK_PIPELINE_BIND_POINT_RANGE_SIZE; ++i) { 359372d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis pCB->lastBound[i].reset(); 359472d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis } 359593c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski 35965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis memset(&pCB->activeRenderPassBeginInfo, 0, sizeof(pCB->activeRenderPassBeginInfo)); 3597ee691f5c5fa87aac3750454d2bca2cb582e4e817Chris Forbes pCB->activeRenderPass = nullptr; 35985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->activeSubpassContents = VK_SUBPASS_CONTENTS_INLINE; 35995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->activeSubpass = 0; 3600e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis pCB->broken_bindings.clear(); 36015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->waitedEvents.clear(); 36025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->events.clear(); 3603c7e6bc41aa9c6e5a677b138b9459b252cd3bedf2Mark Lobodzinski pCB->writeEventsBeforeWait.clear(); 36045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->waitedEventsBeforeQueryReset.clear(); 36055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->queryToStateMap.clear(); 36065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->activeQueries.clear(); 36075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->startedQueries.clear(); 3608abfafae4ec5d76e520916b03d196e474e972c949Michael Lentine pCB->imageSubresourceMap.clear(); 36095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->imageLayoutMap.clear(); 36105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->eventToStageMap.clear(); 36115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->drawData.clear(); 36125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->currentDrawData.buffers.clear(); 361358b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis pCB->vertex_buffer_used = false; 36145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->primaryCommandBuffer = VK_NULL_HANDLE; 3615bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis // Make sure any secondaryCommandBuffers are removed from globalInFlight 3616bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis for (auto secondary_cb : pCB->secondaryCommandBuffers) { 3617bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis dev_data->globalInFlightCmdBuffers.erase(secondary_cb); 3618bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis } 36195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->secondaryCommandBuffers.clear(); 36207a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis pCB->updateImages.clear(); 36217a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis pCB->updateBuffers.clear(); 3622400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis clear_cmd_buf_and_mem_references(dev_data, pCB); 3623b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine pCB->eventUpdates.clear(); 3624d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine pCB->queryUpdates.clear(); 362593c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski 3626bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis // Remove object bindings 3627bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis for (auto obj : pCB->object_bindings) { 3628bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis removeCommandBufferBinding(dev_data, &obj, pCB); 3629bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis } 3630a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis pCB->object_bindings.clear(); 363193c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski // Remove this cmdBuffer's reference from each FrameBuffer's CB ref list 363293c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski for (auto framebuffer : pCB->framebuffers) { 36339a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto fb_state = GetFramebufferState(dev_data, framebuffer); 3634cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (fb_state) fb_state->cb_bindings.erase(pCB); 363593c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski } 363693c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski pCB->framebuffers.clear(); 36377003b38da5cc27a063af3c45080f3a35438283eeTobin Ehlis pCB->activeFramebuffer = VK_NULL_HANDLE; 36385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 36395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 36405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 36415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Set PSO-related status bits for CB, including dynamic state set via PSO 36424c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlisstatic void set_cb_pso_status(GLOBAL_CB_NODE *pCB, const PIPELINE_STATE *pPipe) { 36435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Account for any dynamic state not set via this PSO 3644ca546210846c65808717f8875deae39bd227c240Tobin Ehlis if (!pPipe->graphicsPipelineCI.pDynamicState || 3645cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski !pPipe->graphicsPipelineCI.pDynamicState->dynamicStateCount) { // All state is static 36464052946ae557337ff95f3725e879131b1c63f865Tobin Ehlis pCB->status |= CBSTATUS_ALL_STATE_SET; 36475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 36485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // First consider all state on 36495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Then unset any state that's noted as dynamic in PSO 36505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Finally OR that into CB statemask 36514052946ae557337ff95f3725e879131b1c63f865Tobin Ehlis CBStatusFlags psoDynStateMask = CBSTATUS_ALL_STATE_SET; 3652ca546210846c65808717f8875deae39bd227c240Tobin Ehlis for (uint32_t i = 0; i < pPipe->graphicsPipelineCI.pDynamicState->dynamicStateCount; i++) { 3653ca546210846c65808717f8875deae39bd227c240Tobin Ehlis switch (pPipe->graphicsPipelineCI.pDynamicState->pDynamicStates[i]) { 3654cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DYNAMIC_STATE_LINE_WIDTH: 3655cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski psoDynStateMask &= ~CBSTATUS_LINE_WIDTH_SET; 3656cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3657cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DYNAMIC_STATE_DEPTH_BIAS: 3658cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski psoDynStateMask &= ~CBSTATUS_DEPTH_BIAS_SET; 3659cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3660cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DYNAMIC_STATE_BLEND_CONSTANTS: 3661cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski psoDynStateMask &= ~CBSTATUS_BLEND_CONSTANTS_SET; 3662cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3663cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DYNAMIC_STATE_DEPTH_BOUNDS: 3664cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski psoDynStateMask &= ~CBSTATUS_DEPTH_BOUNDS_SET; 3665cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3666cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK: 3667cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski psoDynStateMask &= ~CBSTATUS_STENCIL_READ_MASK_SET; 3668cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3669cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DYNAMIC_STATE_STENCIL_WRITE_MASK: 3670cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski psoDynStateMask &= ~CBSTATUS_STENCIL_WRITE_MASK_SET; 3671cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3672cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DYNAMIC_STATE_STENCIL_REFERENCE: 3673cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski psoDynStateMask &= ~CBSTATUS_STENCIL_REFERENCE_SET; 3674cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3675cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 3676cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // TODO : Flag error here 3677cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 36785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 36795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 36805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->status |= psoDynStateMask; 36815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 36825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 36835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3684623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski// Flags validation error if the associated call is made inside a render pass. The apiName routine should ONLY be called outside a 3685623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski// render pass. 368651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisbool insideRenderPass(const layer_data *dev_data, GLOBAL_CB_NODE *pCB, const char *apiName, UNIQUE_VALIDATION_ERROR_CODE msgCode) { 3687e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool inside = false; 36885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB->activeRenderPass) { 368951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis inside = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 3690ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen (uint64_t)pCB->commandBuffer, __LINE__, msgCode, "DS", 3691ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen "%s: It is invalid to issue this call inside an active render pass (0x%" PRIxLEAST64 "). %s", apiName, 3692ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen (uint64_t)pCB->activeRenderPass->renderPass, validation_error_map[msgCode]); 36935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 36945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return inside; 36955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 36965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 36975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Flags validation error if the associated call is made outside a render pass. The apiName 36985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// routine should ONLY be called inside a render pass. 369951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisbool outsideRenderPass(const layer_data *dev_data, GLOBAL_CB_NODE *pCB, const char *apiName, UNIQUE_VALIDATION_ERROR_CODE msgCode) { 3700e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool outside = false; 37015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (((pCB->createInfo.level == VK_COMMAND_BUFFER_LEVEL_PRIMARY) && (!pCB->activeRenderPass)) || 37025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis ((pCB->createInfo.level == VK_COMMAND_BUFFER_LEVEL_SECONDARY) && (!pCB->activeRenderPass) && 37035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis !(pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT))) { 370451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis outside = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 3705ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen (uint64_t)pCB->commandBuffer, __LINE__, msgCode, "DS", 3706ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen "%s: This call must be issued inside an active render pass. %s", apiName, validation_error_map[msgCode]); 37075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 37085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return outside; 37095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 37105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3711f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbesstatic void init_core_validation(instance_layer_data *instance_data, const VkAllocationCallbacks *pAllocator) { 3712b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis layer_debug_actions(instance_data->report_data, instance_data->logging_callback, pAllocator, "lunarg_core_validation"); 37135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 37145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3715747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbesstatic void checkInstanceRegisterExtensions(const VkInstanceCreateInfo *pCreateInfo, instance_layer_data *instance_data) { 3716747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) { 3717747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SURFACE_EXTENSION_NAME)) 3718747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->surfaceExtensionEnabled = true; 3719747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_DISPLAY_EXTENSION_NAME)) 3720747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->displayExtensionEnabled = true; 3721747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_ANDROID_KHR 3722747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_ANDROID_SURFACE_EXTENSION_NAME)) 3723747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->androidSurfaceExtensionEnabled = true; 3724747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif 3725747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_MIR_KHR 3726747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_MIR_SURFACE_EXTENSION_NAME)) 3727747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->mirSurfaceExtensionEnabled = true; 3728747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif 3729747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_WAYLAND_KHR 3730747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME)) 3731747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->waylandSurfaceExtensionEnabled = true; 3732747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif 3733747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_WIN32_KHR 3734747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_WIN32_SURFACE_EXTENSION_NAME)) 3735747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->win32SurfaceExtensionEnabled = true; 3736747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif 3737747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_XCB_KHR 3738747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_XCB_SURFACE_EXTENSION_NAME)) 3739747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->xcbSurfaceExtensionEnabled = true; 3740747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif 3741747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_XLIB_KHR 3742747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_XLIB_SURFACE_EXTENSION_NAME)) 3743747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->xlibSurfaceExtensionEnabled = true; 3744747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif 3745747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes } 3746747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 3747747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 3748bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, 3749bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkInstance *pInstance) { 37505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO); 37515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 37525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(chain_info->u.pLayerInfo); 37535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr; 37545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance"); 3755cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED; 37565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 37575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Advance the link info for the next element on the chain 37585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext; 37595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 37605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance); 3761cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (result != VK_SUCCESS) return result; 37625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 376356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(*pInstance), instance_layer_data_map); 376456a5ba3e60a723781945959ffc10e2e215350de5Chia-I Wu instance_data->instance = *pInstance; 37659172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes layer_init_instance_dispatch_table(*pInstance, &instance_data->dispatch_table, fpGetInstanceProcAddr); 37669172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes instance_data->report_data = debug_report_create_instance( 37679172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes &instance_data->dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount, pCreateInfo->ppEnabledExtensionNames); 3768747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes checkInstanceRegisterExtensions(pCreateInfo, instance_data); 3769b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis init_core_validation(instance_data, pAllocator); 3770825ac70f99460ccb9494d34f93d8ee7ec303e5deMark Lobodzinski 37715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis ValidateLayerOrdering(*pCreateInfo); 37725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 37735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 37745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 37755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 377625002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// Hook DestroyInstance to remove tableInstanceMap entry 377789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) { 37785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODOSC : Shouldn't need any customization here 37795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dispatch_key key = get_dispatch_key(instance); 37805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TBD: Need any locking this early, in case this function is called at the 37815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // same time by more than one thread? 378256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(key, instance_layer_data_map); 37839172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes instance_data->dispatch_table.DestroyInstance(instance, pAllocator); 37845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3785b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 37865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Clean up logging callback, if any 37879172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes while (instance_data->logging_callback.size() > 0) { 37889172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes VkDebugReportCallbackEXT callback = instance_data->logging_callback.back(); 37899172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes layer_destroy_msg_callback(instance_data->report_data, callback, pAllocator); 37909172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes instance_data->logging_callback.pop_back(); 37915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 37925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 37939172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes layer_debug_report_destroy_instance(instance_data->report_data); 37945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis layer_data_map.erase(key); 37955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 37965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3797373469f006399d6b5204ee05db3b56beb168b36fMark Youngstatic void checkDeviceRegisterExtensions(const VkDeviceCreateInfo *pCreateInfo, VkDevice device) { 37985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t i; 3799bee1d36c54af112766d4e8552ad302f39290683aMark Lobodzinski // TBD: Need any locking, in case this function is called at the same time by more than one thread? 380056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 38015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->device_extensions.wsi_enabled = false; 3802c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young dev_data->device_extensions.wsi_display_swapchain_enabled = false; 3803bee1d36c54af112766d4e8552ad302f39290683aMark Lobodzinski dev_data->device_extensions.nv_glsl_shader_enabled = false; 38045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 38055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (i = 0; i < pCreateInfo->enabledExtensionCount; i++) { 3806bee1d36c54af112766d4e8552ad302f39290683aMark Lobodzinski if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SWAPCHAIN_EXTENSION_NAME) == 0) { 38075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->device_extensions.wsi_enabled = true; 3808bee1d36c54af112766d4e8552ad302f39290683aMark Lobodzinski } 3809bee1d36c54af112766d4e8552ad302f39290683aMark Lobodzinski if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_DISPLAY_SWAPCHAIN_EXTENSION_NAME) == 0) { 3810c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young dev_data->device_extensions.wsi_display_swapchain_enabled = true; 3811bee1d36c54af112766d4e8552ad302f39290683aMark Lobodzinski } 3812bee1d36c54af112766d4e8552ad302f39290683aMark Lobodzinski if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_NV_GLSL_SHADER_EXTENSION_NAME) == 0) { 3813bee1d36c54af112766d4e8552ad302f39290683aMark Lobodzinski dev_data->device_extensions.nv_glsl_shader_enabled = true; 3814bee1d36c54af112766d4e8552ad302f39290683aMark Lobodzinski } 38155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 38165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 38175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3818838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski// Verify that queue family has been properly requested 3819ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblenstatic bool ValidateRequestedQueueFamilyProperties(instance_layer_data *instance_data, VkPhysicalDevice gpu, 3820ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen const VkDeviceCreateInfo *create_info) { 3821838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski bool skip_call = false; 38229a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto physical_device_state = GetPhysicalDeviceState(instance_data, gpu); 3823838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski // First check is app has actually requested queueFamilyProperties 38244b293996aa6a9bd92ef1f0175eca4b0e8a9fd9fcChris Forbes if (!physical_device_state) { 3825bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski skip_call |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 3826bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_MUST_QUERY_COUNT, "DL", 3827838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski "Invalid call to vkCreateDevice() w/o first calling vkEnumeratePhysicalDevices()."); 38284b293996aa6a9bd92ef1f0175eca4b0e8a9fd9fcChris Forbes } else if (QUERY_DETAILS != physical_device_state->vkGetPhysicalDeviceQueueFamilyPropertiesState) { 3829838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski // TODO: This is not called out as an invalid use in the spec so make more informative recommendation. 38304b293996aa6a9bd92ef1f0175eca4b0e8a9fd9fcChris Forbes skip_call |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, 3831838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_INVALID_QUEUE_CREATE_REQUEST, 3832838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski "DL", "Call to vkCreateDevice() w/o first calling vkGetPhysicalDeviceQueueFamilyProperties()."); 3833838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski } else { 3834838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski // Check that the requested queue properties are valid 3835838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski for (uint32_t i = 0; i < create_info->queueCreateInfoCount; i++) { 3836838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski uint32_t requestedIndex = create_info->pQueueCreateInfos[i].queueFamilyIndex; 38377d8b6ab1b68c397da50bad43deb1fba389ebace7Chris Forbes if (requestedIndex >= physical_device_state->queue_family_properties.size()) { 3838838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski skip_call |= log_msg( 38394b293996aa6a9bd92ef1f0175eca4b0e8a9fd9fcChris Forbes instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, 3840838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski __LINE__, DEVLIMITS_INVALID_QUEUE_CREATE_REQUEST, "DL", 3841838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski "Invalid queue create request in vkCreateDevice(). Invalid queueFamilyIndex %u requested.", requestedIndex); 3842838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski } else if (create_info->pQueueCreateInfos[i].queueCount > 38437d8b6ab1b68c397da50bad43deb1fba389ebace7Chris Forbes physical_device_state->queue_family_properties[requestedIndex].queueCount) { 3844cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski skip_call |= log_msg( 3845cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, 3846cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, DEVLIMITS_INVALID_QUEUE_CREATE_REQUEST, "DL", 3847cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Invalid queue create request in vkCreateDevice(). QueueFamilyIndex %u only has %u queues, but " 3848cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "requested queueCount is %u.", 3849cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski requestedIndex, physical_device_state->queue_family_properties[requestedIndex].queueCount, 3850cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski create_info->pQueueCreateInfos[i].queueCount); 3851838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski } 3852838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski } 3853838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski } 3854838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski return skip_call; 3855838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski} 3856838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski 3857f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski// Verify that features have been queried and that they are available 3858bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic bool ValidateRequestedFeatures(instance_layer_data *dev_data, VkPhysicalDevice phys, 3859bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkPhysicalDeviceFeatures *requested_features) { 3860f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski bool skip_call = false; 3861f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski 38629a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto phys_device_state = GetPhysicalDeviceState(dev_data, phys); 38633bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes const VkBool32 *actual = reinterpret_cast<VkBool32 *>(&phys_device_state->features); 3864825ac70f99460ccb9494d34f93d8ee7ec303e5deMark Lobodzinski const VkBool32 *requested = reinterpret_cast<const VkBool32 *>(requested_features); 3865f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski // TODO : This is a nice, compact way to loop through struct, but a bad way to report issues 3866f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski // Need to provide the struct member name with the issue. To do that seems like we'll 3867f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski // have to loop through each struct member which should be done w/ codegen to keep in synch. 3868f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski uint32_t errors = 0; 3869f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski uint32_t total_bools = sizeof(VkPhysicalDeviceFeatures) / sizeof(VkBool32); 3870f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski for (uint32_t i = 0; i < total_bools; i++) { 3871f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski if (requested[i] > actual[i]) { 3872f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski // TODO: Add index to struct member name helper to be able to include a feature name 3873cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski skip_call |= 3874cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, 3875cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, DEVLIMITS_INVALID_FEATURE_REQUESTED, "DL", 3876cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "While calling vkCreateDevice(), requesting feature #%u in VkPhysicalDeviceFeatures struct, " 3877cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "which is not available on this device.", 3878cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski i); 3879f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski errors++; 3880f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski } 3881f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski } 38823bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes if (errors && (UNCALLED == phys_device_state->vkGetPhysicalDeviceFeaturesState)) { 3883f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski // If user didn't request features, notify them that they should 3884f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski // TODO: Verify this against the spec. I believe this is an invalid use of the API and should return an error 3885bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 3886bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski 0, __LINE__, DEVLIMITS_INVALID_FEATURE_REQUESTED, "DL", 3887bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "You requested features that are unavailable on this device. You should first query feature " 3888bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "availability by calling vkGetPhysicalDeviceFeatures()."); 3889f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski } 3890f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski return skip_call; 3891f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski} 3892f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski 389389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo, 389489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) { 389556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(gpu), instance_layer_data_map); 3896f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski bool skip_call = false; 3897f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski 3898f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski // Check that any requested features are available 3899f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski if (pCreateInfo->pEnabledFeatures) { 390056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis skip_call |= ValidateRequestedFeatures(instance_data, gpu, pCreateInfo->pEnabledFeatures); 3901f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski } 390256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis skip_call |= ValidateRequestedQueueFamilyProperties(instance_data, gpu, pCreateInfo); 3903f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski 39041d659b4113b77a95325df10d602a03f1e7abf8b7Mark Mueller if (skip_call) { 39051d659b4113b77a95325df10d602a03f1e7abf8b7Mark Mueller return VK_ERROR_VALIDATION_FAILED_EXT; 39061d659b4113b77a95325df10d602a03f1e7abf8b7Mark Mueller } 39071d659b4113b77a95325df10d602a03f1e7abf8b7Mark Mueller 39085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO); 39095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 39105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(chain_info->u.pLayerInfo); 39115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr; 39125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr; 391356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_data->instance, "vkCreateDevice"); 39145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (fpCreateDevice == NULL) { 39155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return VK_ERROR_INITIALIZATION_FAILED; 39165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 39175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 39185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Advance the link info for the next element on the chain 39195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext; 39205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 39215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice); 39225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (result != VK_SUCCESS) { 39235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 39245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 39255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3926b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 392756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *device_data = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map); 39285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 392956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis device_data->instance_data = instance_data; 39305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Setup device dispatch table 393156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_init_device_dispatch_table(*pDevice, &device_data->dispatch_table, fpGetDeviceProcAddr); 393256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis device_data->device = *pDevice; 3933ec85232c4d8d9ddf7d2ae57cb8203c5ab52c1106Mark Lobodzinski // Save PhysicalDevice handle 393456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis device_data->physical_device = gpu; 39355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 393656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis device_data->report_data = layer_debug_report_create_device(instance_data->report_data, *pDevice); 3937373469f006399d6b5204ee05db3b56beb168b36fMark Young checkDeviceRegisterExtensions(pCreateInfo, *pDevice); 39385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Get physical device limits for this device 393956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_data->dispatch_table.GetPhysicalDeviceProperties(gpu, &(device_data->phys_dev_properties.properties)); 39405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t count; 394156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_data->dispatch_table.GetPhysicalDeviceQueueFamilyProperties(gpu, &count, nullptr); 394256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis device_data->phys_dev_properties.queue_family_properties.resize(count); 394356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_data->dispatch_table.GetPhysicalDeviceQueueFamilyProperties( 394456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis gpu, &count, &device_data->phys_dev_properties.queue_family_properties[0]); 39455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODO: device limits should make sure these are compatible 39465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCreateInfo->pEnabledFeatures) { 394756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis device_data->enabled_features = *pCreateInfo->pEnabledFeatures; 39485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 394956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis memset(&device_data->enabled_features, 0, sizeof(VkPhysicalDeviceFeatures)); 39505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 3951e47dbc3f3340fa177d877a67b2adb76a570027e5Mark Lobodzinski // Store physical device properties and physical device mem limits into device layer_data structs 395256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_data->dispatch_table.GetPhysicalDeviceMemoryProperties(gpu, &device_data->phys_dev_mem_props); 395356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_data->dispatch_table.GetPhysicalDeviceProperties(gpu, &device_data->phys_dev_props); 3954b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 39555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 39565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis ValidateLayerOrdering(*pCreateInfo); 39575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 39585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 39595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 39605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 39615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// prototype 396289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) { 39635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODOSC : Shouldn't need any customization here 39643ec39aeb6d6f08fb1ee45f64f72543a710754c62Tobin Ehlis bool skip = false; 39655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dispatch_key key = get_dispatch_key(device); 396656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(key, layer_data_map); 39675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Free all the memory 3968b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 39695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis deletePipelines(dev_data); 3970fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes dev_data->renderPassMap.clear(); 39715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis deleteCommandBuffers(dev_data); 3972f13bee0887f3c3d1d597c82869864be3be836737Tobin Ehlis // This will also delete all sets in the pool & remove them from setMap 39735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis deletePools(dev_data); 3974f13bee0887f3c3d1d597c82869864be3be836737Tobin Ehlis // All sets should be removed 3975f13bee0887f3c3d1d597c82869864be3be836737Tobin Ehlis assert(dev_data->setMap.empty()); 3976a1e5173c89eb7f03e0434ad45ccd1471e722fa71Tobin Ehlis for (auto del_layout : dev_data->descriptorSetLayoutMap) { 3977a1e5173c89eb7f03e0434ad45ccd1471e722fa71Tobin Ehlis delete del_layout.second; 3978a1e5173c89eb7f03e0434ad45ccd1471e722fa71Tobin Ehlis } 3979fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis dev_data->descriptorSetLayoutMap.clear(); 39805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->imageViewMap.clear(); 39815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->imageMap.clear(); 39825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->imageSubresourceMap.clear(); 39835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->imageLayoutMap.clear(); 39845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->bufferViewMap.clear(); 39855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->bufferMap.clear(); 39861344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis // Queues persist until device is destroyed 39871344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis dev_data->queueMap.clear(); 39885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Report any memory leaks 39895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis layer_debug_report_destroy_device(device); 3990b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 39915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 39925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#if DISPATCH_MAP_DEBUG 3993414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller fprintf(stderr, "Device: 0x%p, key: 0x%p\n", device, key); 39945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#endif 39953ec39aeb6d6f08fb1ee45f64f72543a710754c62Tobin Ehlis if (!skip) { 39964a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyDevice(device, pAllocator); 39973ec39aeb6d6f08fb1ee45f64f72543a710754c62Tobin Ehlis layer_data_map.erase(key); 39985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 39995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 40005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 40015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}}; 40025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4003208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis// For given stage mask, if Geometry shader stage is on w/o GS being enabled, report geo_error_id 4004208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis// and if Tessellation Control or Evaluation shader stages are on w/o TS being enabled, report tess_error_id 4005208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlisstatic bool ValidateStageMaskGsTsEnables(layer_data *dev_data, VkPipelineStageFlags stageMask, const char *caller, 4006208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis UNIQUE_VALIDATION_ERROR_CODE geo_error_id, UNIQUE_VALIDATION_ERROR_CODE tess_error_id) { 4007208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis bool skip = false; 4008208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis if (!dev_data->enabled_features.geometryShader && (stageMask & VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT)) { 4009208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 4010cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski geo_error_id, "DL", 4011cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s call includes a stageMask with VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT bit set when " 4012cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "device does not have geometryShader feature enabled. %s", 4013208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis caller, validation_error_map[geo_error_id]); 4014208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis } 4015208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis if (!dev_data->enabled_features.tessellationShader && 4016208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis (stageMask & (VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT | VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT))) { 4017208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 4018cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski tess_error_id, "DL", 4019cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s call includes a stageMask with VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT " 4020cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "and/or VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT bit(s) set when device " 4021cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "does not have tessellationShader feature enabled. %s", 4022208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis caller, validation_error_map[tess_error_id]); 4023208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis } 4024208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis return skip; 4025208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis} 4026208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis 402751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour// Loop through bound objects and increment their in_use counts if increment parameter is true 402851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour// or flag an error if unknown objects are found 402951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourstatic bool ValidateOrIncrementBoundObjects(layer_data *dev_data, GLOBAL_CB_NODE const *cb_node, bool increment) { 4030162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis bool skip = false; 4031162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis DRAW_STATE_ERROR error_code = DRAWSTATE_NONE; 4032162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis BASE_NODE *base_obj = nullptr; 4033a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis for (auto obj : cb_node->object_bindings) { 4034a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis switch (obj.type) { 4035cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT: { 40369a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_obj = GetSetNode(dev_data, reinterpret_cast<VkDescriptorSet &>(obj.handle)); 4037cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski error_code = DRAWSTATE_INVALID_DESCRIPTOR_SET; 4038cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 4039cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 4040cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT: { 40419a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_obj = GetSamplerState(dev_data, reinterpret_cast<VkSampler &>(obj.handle)); 4042cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski error_code = DRAWSTATE_INVALID_SAMPLER; 4043cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 4044cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 4045cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT: { 40469a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_obj = GetQueryPoolNode(dev_data, reinterpret_cast<VkQueryPool &>(obj.handle)); 4047cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski error_code = DRAWSTATE_INVALID_QUERY_POOL; 4048cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 4049cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 4050cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT: { 4051cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski base_obj = getPipelineState(dev_data, reinterpret_cast<VkPipeline &>(obj.handle)); 4052cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski error_code = DRAWSTATE_INVALID_PIPELINE; 4053cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 4054cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 4055cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT: { 40569a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_obj = GetBufferState(dev_data, reinterpret_cast<VkBuffer &>(obj.handle)); 4057cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski error_code = DRAWSTATE_INVALID_BUFFER; 4058cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 4059cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 4060cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT: { 40619a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_obj = GetBufferViewState(dev_data, reinterpret_cast<VkBufferView &>(obj.handle)); 4062cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski error_code = DRAWSTATE_INVALID_BUFFER_VIEW; 4063cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 4064cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 4065cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT: { 40669a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_obj = GetImageState(dev_data, reinterpret_cast<VkImage &>(obj.handle)); 4067cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski error_code = DRAWSTATE_INVALID_IMAGE; 4068cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 4069cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 4070cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT: { 40719a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_obj = GetImageViewState(dev_data, reinterpret_cast<VkImageView &>(obj.handle)); 4072cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski error_code = DRAWSTATE_INVALID_IMAGE_VIEW; 4073cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 4074cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 4075cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT: { 40769a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_obj = GetEventNode(dev_data, reinterpret_cast<VkEvent &>(obj.handle)); 4077cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski error_code = DRAWSTATE_INVALID_EVENT; 4078cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 4079cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 4080cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT: { 40819a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_obj = GetDescriptorPoolState(dev_data, reinterpret_cast<VkDescriptorPool &>(obj.handle)); 4082cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski error_code = DRAWSTATE_INVALID_DESCRIPTOR_POOL; 4083cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 4084cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 4085cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT: { 40869a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_obj = GetCommandPoolNode(dev_data, reinterpret_cast<VkCommandPool &>(obj.handle)); 4087cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski error_code = DRAWSTATE_INVALID_COMMAND_POOL; 4088cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 4089cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 4090cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT: { 40919a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_obj = GetFramebufferState(dev_data, reinterpret_cast<VkFramebuffer &>(obj.handle)); 4092cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski error_code = DRAWSTATE_INVALID_FRAMEBUFFER; 4093cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 4094cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 4095cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT: { 40969a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_obj = GetRenderPassState(dev_data, reinterpret_cast<VkRenderPass &>(obj.handle)); 4097cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski error_code = DRAWSTATE_INVALID_RENDERPASS; 4098cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 4099cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 4100cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT: { 41019a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_obj = GetMemObjInfo(dev_data, reinterpret_cast<VkDeviceMemory &>(obj.handle)); 4102cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski error_code = DRAWSTATE_INVALID_DEVICE_MEMORY; 4103cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 4104cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 4105cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 4106cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // TODO : Merge handling of other objects types into this code 4107cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 4108a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis } 410951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (base_obj && increment) { 411051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour base_obj->in_use.fetch_add(1); 411151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } else if (!base_obj && !increment) { 4112162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis skip |= 4113162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, obj.type, obj.handle, __LINE__, error_code, "DS", 4114162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis "Cannot submit cmd buffer using deleted %s 0x%" PRIx64 ".", object_type_to_string(obj.type), obj.handle); 4115162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis } 4116a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis } 4117162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis return skip; 4118a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis} 41195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Track which resources are in-flight by atomically incrementing their "in_use" count 412051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourstatic void incrementResources(layer_data *dev_data, GLOBAL_CB_NODE *cb_node) { 412151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour cb_node->submitCount++; 41229a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis cb_node->in_use.fetch_add(1); 41239a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis dev_data->globalInFlightCmdBuffers.insert(cb_node->commandBuffer); 4124a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes 4125a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis // First Increment for all "generic" objects bound to cmd buffer, followed by special-case objects below 412651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour ValidateOrIncrementBoundObjects(dev_data, cb_node, true); 4127a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis // TODO : We should be able to remove the NULL look-up checks from the code below as long as 4128a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis // all the corresponding cases are verified to cause CB_INVALID state and the CB_INVALID state 4129a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis // should then be flagged prior to calling this function 41309a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis for (auto drawDataElement : cb_node->drawData) { 41315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto buffer : drawDataElement.buffers) { 41329a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto buffer_state = GetBufferState(dev_data, buffer); 413351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (buffer_state) { 41345cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis buffer_state->in_use.fetch_add(1); 41355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 41365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 41375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 41389a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis for (auto event : cb_node->writeEventsBeforeWait) { 41399a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto event_state = GetEventNode(dev_data, event); 4140cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (event_state) event_state->write_in_use++; 4141c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine } 41425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 41435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4144b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis// Note: This function assumes that the global lock is held by the calling thread. 4145b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis// For the given queue, verify the queue state up to the given seq number. 4146b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis// Currently the only check is to make sure that if there are events to be waited on prior to 4147b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis// a QueryReset, make sure that all such events have been signalled. 414836c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlisstatic bool VerifyQueueStateToSeq(layer_data *dev_data, QUEUE_STATE *queue, uint64_t seq) { 4149b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis bool skip = false; 4150b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis auto queue_seq = queue->seq; 415192b1701c552e96e96fdbbb77e4b106a9526f3b8cTobin Ehlis std::unordered_map<VkQueue, uint64_t> other_queue_seqs; 415292b1701c552e96e96fdbbb77e4b106a9526f3b8cTobin Ehlis auto sub_it = queue->submissions.begin(); 4153b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis while (queue_seq < seq) { 415492b1701c552e96e96fdbbb77e4b106a9526f3b8cTobin Ehlis for (auto &wait : sub_it->waitSemaphores) { 415592b1701c552e96e96fdbbb77e4b106a9526f3b8cTobin Ehlis auto &last_seq = other_queue_seqs[wait.queue]; 415692b1701c552e96e96fdbbb77e4b106a9526f3b8cTobin Ehlis last_seq = std::max(last_seq, wait.seq); 415792b1701c552e96e96fdbbb77e4b106a9526f3b8cTobin Ehlis } 415892b1701c552e96e96fdbbb77e4b106a9526f3b8cTobin Ehlis for (auto cb : sub_it->cbs) { 41599a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, cb); 4160b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis if (cb_node) { 4161b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis for (auto queryEventsPair : cb_node->waitedEventsBeforeQueryReset) { 4162b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis for (auto event : queryEventsPair.second) { 416392b1701c552e96e96fdbbb77e4b106a9526f3b8cTobin Ehlis if (dev_data->eventMap[event].needsSignaled) { 416492b1701c552e96e96fdbbb77e4b106a9526f3b8cTobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 4165b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, 0, DRAWSTATE_INVALID_QUERY, "DS", 4166b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis "Cannot get query results on queryPool 0x%" PRIx64 4167b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis " with index %d which was guarded by unsignaled event 0x%" PRIx64 ".", 4168b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis (uint64_t)(queryEventsPair.first.pool), queryEventsPair.first.index, (uint64_t)(event)); 4169b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis } 4170b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis } 4171b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine } 4172b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine } 4173b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine } 417492b1701c552e96e96fdbbb77e4b106a9526f3b8cTobin Ehlis sub_it++; 4175b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis queue_seq++; 4176b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine } 417792b1701c552e96e96fdbbb77e4b106a9526f3b8cTobin Ehlis for (auto qs : other_queue_seqs) { 41789a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis skip |= VerifyQueueStateToSeq(dev_data, GetQueueState(dev_data, qs.first), qs.second); 417992b1701c552e96e96fdbbb77e4b106a9526f3b8cTobin Ehlis } 4180b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis return skip; 4181b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis} 4182b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis 4183b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis// When the given fence is retired, verify outstanding queue operations through the point of the fence 4184b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlisstatic bool VerifyQueueStateToFence(layer_data *dev_data, VkFence fence) { 41859a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto fence_state = GetFenceNode(dev_data, fence); 4186b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis if (VK_NULL_HANDLE != fence_state->signaler.first) { 41879a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis return VerifyQueueStateToSeq(dev_data, GetQueueState(dev_data, fence_state->signaler.first), fence_state->signaler.second); 4188b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis } 4189b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis return false; 4190b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine} 41917d33205c3aa4aba751a2c07f956634aac616f916Chris Forbes 41927d33205c3aa4aba751a2c07f956634aac616f916Chris Forbes// TODO: nuke this completely. 4193b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine// Decrement cmd_buffer in_use and if it goes to 0 remove cmd_buffer from globalInFlightCmdBuffers 4194b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentinestatic inline void removeInFlightCmdBuffer(layer_data *dev_data, VkCommandBuffer cmd_buffer) { 4195b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine // Pull it off of global list initially, but if we find it in any other queue list, add it back in 41969a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, cmd_buffer); 4197b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine pCB->in_use.fetch_sub(1); 4198b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine if (!pCB->in_use.load()) { 4199b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine dev_data->globalInFlightCmdBuffers.erase(cmd_buffer); 4200b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine } 4201b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine} 4202b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine 4203a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis// Decrement in-use count for objects bound to command buffer 42042f8cbf3b166e175174877a59929902e005953d6dTobin Ehlisstatic void DecrementBoundResources(layer_data *dev_data, GLOBAL_CB_NODE const *cb_node) { 420500e8ce2e6c1c191758f7b7c15eeaf350e5b4a3b6Tobin Ehlis BASE_NODE *base_obj = nullptr; 4206a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis for (auto obj : cb_node->object_bindings) { 42077e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis base_obj = GetStateStructPtrFromObject(dev_data, obj); 420800e8ce2e6c1c191758f7b7c15eeaf350e5b4a3b6Tobin Ehlis if (base_obj) { 420900e8ce2e6c1c191758f7b7c15eeaf350e5b4a3b6Tobin Ehlis base_obj->in_use.fetch_sub(1); 421000e8ce2e6c1c191758f7b7c15eeaf350e5b4a3b6Tobin Ehlis } 4211a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis } 4212a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis} 4213da8f07baf262972eb3e719fa07b073c180dff157Chris Forbes 421436c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlisstatic void RetireWorkOnQueue(layer_data *dev_data, QUEUE_STATE *pQueue, uint64_t seq) { 42159867daedbf52debc77d6568162ee21e071699b80Chris Forbes std::unordered_map<VkQueue, uint64_t> otherQueueSeqs; 42169867daedbf52debc77d6568162ee21e071699b80Chris Forbes 42179867daedbf52debc77d6568162ee21e071699b80Chris Forbes // Roll this queue forward, one submission at a time. 42189867daedbf52debc77d6568162ee21e071699b80Chris Forbes while (pQueue->seq < seq) { 4219bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto &submission = pQueue->submissions.front(); 42209867daedbf52debc77d6568162ee21e071699b80Chris Forbes 4221bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski for (auto &wait : submission.waitSemaphores) { 42229a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pSemaphore = GetSemaphoreNode(dev_data, wait.semaphore); 4223c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski if (pSemaphore) { 4224c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski pSemaphore->in_use.fetch_sub(1); 4225c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski } 4226bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto &lastSeq = otherQueueSeqs[wait.queue]; 42279867daedbf52debc77d6568162ee21e071699b80Chris Forbes lastSeq = std::max(lastSeq, wait.seq); 4228da8f07baf262972eb3e719fa07b073c180dff157Chris Forbes } 4229cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes 4230bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski for (auto &semaphore : submission.signalSemaphores) { 42319a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pSemaphore = GetSemaphoreNode(dev_data, semaphore); 4232c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski if (pSemaphore) { 4233c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski pSemaphore->in_use.fetch_sub(1); 4234c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski } 42359867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 4236cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes 42379867daedbf52debc77d6568162ee21e071699b80Chris Forbes for (auto cb : submission.cbs) { 42389a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, cb); 4239c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski if (!cb_node) { 4240c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski continue; 4241c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski } 4242a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis // First perform decrement on general case bound objects 42439a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis DecrementBoundResources(dev_data, cb_node); 42449a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis for (auto drawDataElement : cb_node->drawData) { 42459867daedbf52debc77d6568162ee21e071699b80Chris Forbes for (auto buffer : drawDataElement.buffers) { 42469a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto buffer_state = GetBufferState(dev_data, buffer); 42475cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis if (buffer_state) { 42485cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis buffer_state->in_use.fetch_sub(1); 42499867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 42509867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 4251da8f07baf262972eb3e719fa07b073c180dff157Chris Forbes } 42529a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis for (auto event : cb_node->writeEventsBeforeWait) { 42539867daedbf52debc77d6568162ee21e071699b80Chris Forbes auto eventNode = dev_data->eventMap.find(event); 42549867daedbf52debc77d6568162ee21e071699b80Chris Forbes if (eventNode != dev_data->eventMap.end()) { 42559867daedbf52debc77d6568162ee21e071699b80Chris Forbes eventNode->second.write_in_use--; 42569867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 42579867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 42589a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis for (auto queryStatePair : cb_node->queryToStateMap) { 42599867daedbf52debc77d6568162ee21e071699b80Chris Forbes dev_data->queryToStateMap[queryStatePair.first] = queryStatePair.second; 42609867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 42619a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis for (auto eventStagePair : cb_node->eventToStageMap) { 42629867daedbf52debc77d6568162ee21e071699b80Chris Forbes dev_data->eventMap[eventStagePair.first].stageMask = eventStagePair.second; 4263da8f07baf262972eb3e719fa07b073c180dff157Chris Forbes } 42640a32ed7bdf03e7bda914e03c0bfa6ebf400cdf5bMichael Lentine 42659867daedbf52debc77d6568162ee21e071699b80Chris Forbes removeInFlightCmdBuffer(dev_data, cb); 42660a32ed7bdf03e7bda914e03c0bfa6ebf400cdf5bMichael Lentine } 42679867daedbf52debc77d6568162ee21e071699b80Chris Forbes 42689a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pFence = GetFenceNode(dev_data, submission.fence); 42699867daedbf52debc77d6568162ee21e071699b80Chris Forbes if (pFence) { 42709867daedbf52debc77d6568162ee21e071699b80Chris Forbes pFence->state = FENCE_RETIRED; 42710a32ed7bdf03e7bda914e03c0bfa6ebf400cdf5bMichael Lentine } 42729867daedbf52debc77d6568162ee21e071699b80Chris Forbes 42739867daedbf52debc77d6568162ee21e071699b80Chris Forbes pQueue->submissions.pop_front(); 42749867daedbf52debc77d6568162ee21e071699b80Chris Forbes pQueue->seq++; 4275b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine } 42769867daedbf52debc77d6568162ee21e071699b80Chris Forbes 42779867daedbf52debc77d6568162ee21e071699b80Chris Forbes // Roll other queues forward to the highest seq we saw a wait for 42789867daedbf52debc77d6568162ee21e071699b80Chris Forbes for (auto qs : otherQueueSeqs) { 42799a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis RetireWorkOnQueue(dev_data, GetQueueState(dev_data, qs.first), qs.second); 4280d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 42819867daedbf52debc77d6568162ee21e071699b80Chris Forbes} 4282651d92815dfff917308137bb67aacccc4f60df86Chris Forbes 4283651d92815dfff917308137bb67aacccc4f60df86Chris Forbes// Submit a fence to a queue, delimiting previous fences and previous untracked 4284651d92815dfff917308137bb67aacccc4f60df86Chris Forbes// work by it. 428536c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlisstatic void SubmitFence(QUEUE_STATE *pQueue, FENCE_NODE *pFence, uint64_t submitCount) { 4286cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes pFence->state = FENCE_INFLIGHT; 42879867daedbf52debc77d6568162ee21e071699b80Chris Forbes pFence->signaler.first = pQueue->queue; 42889867daedbf52debc77d6568162ee21e071699b80Chris Forbes pFence->signaler.second = pQueue->seq + pQueue->submissions.size() + submitCount; 4289b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine} 4290b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine 429151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourstatic bool validateCommandBufferSimultaneousUse(layer_data *dev_data, GLOBAL_CB_NODE *pCB, int current_submit_count) { 42925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool skip_call = false; 429351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if ((dev_data->globalInFlightCmdBuffers.count(pCB->commandBuffer) || current_submit_count > 1) && 42945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis !(pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT)) { 4295226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 4296f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen 0, __LINE__, VALIDATION_ERROR_00133, "DS", 4297f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen "Command Buffer 0x%p is already in use and is not marked for simultaneous use. %s", pCB->commandBuffer, 4298f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen validation_error_map[VALIDATION_ERROR_00133]); 42995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 43005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return skip_call; 43015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 43025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4303440bdd357701497c3442e3515f12ac1cfffc180aTony Barbourstatic bool validateCommandBufferState(layer_data *dev_data, GLOBAL_CB_NODE *pCB, const char *call_source, 4304440bdd357701497c3442e3515f12ac1cfffc180aTony Barbour int current_submit_count) { 4305c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis bool skip = false; 4306cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.command_buffer_state) return skip; 43070a59acde4b40fde3bbfea5811d2abf2c85ca62f4Tobin Ehlis // Validate ONE_TIME_SUBMIT_BIT CB is not being submitted more than once 430851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if ((pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT) && (pCB->submitCount + current_submit_count > 1)) { 4309c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, 4310c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis __LINE__, DRAWSTATE_COMMAND_BUFFER_SINGLE_SUBMIT_VIOLATION, "DS", 4311226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "Commandbuffer 0x%p was begun w/ VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT " 4312c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis "set, but has been submitted 0x%" PRIxLEAST64 " times.", 431351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pCB->commandBuffer, pCB->submitCount + current_submit_count); 43140a59acde4b40fde3bbfea5811d2abf2c85ca62f4Tobin Ehlis } 43155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Validate that cmd buffers have been updated 43165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (CB_RECORDED != pCB->state) { 43175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (CB_INVALID == pCB->state) { 43185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Inform app of reason CB invalid 4319e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis for (auto obj : pCB->broken_bindings) { 4320e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis const char *type_str = object_type_to_string(obj.type); 4321e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis // Descriptor sets are a special case that can be either destroyed or updated to invalidated a CB 4322e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis const char *cause_str = 4323e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis (obj.type == VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT) ? "destroyed or updated" : "destroyed"; 43245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4325c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis skip |= 43265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 43275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis reinterpret_cast<uint64_t &>(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER, "DS", 4328226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "You are submitting command buffer 0x%p that is invalid because bound %s 0x%" PRIxLEAST64 " was %s.", 4329226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis pCB->commandBuffer, type_str, obj.handle, cause_str); 43305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 4331cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else { // Flag error for using CB w/o vkEndCommandBuffer() called 4332c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 4333c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis (uint64_t)(pCB->commandBuffer), __LINE__, DRAWSTATE_NO_END_COMMAND_BUFFER, "DS", 4334226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "You must call vkEndCommandBuffer() on command buffer 0x%p before this call to %s!", pCB->commandBuffer, 4335226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis call_source); 43365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 43375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 4338c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis return skip; 43395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 43405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 434151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourstatic bool validateResources(layer_data *dev_data, GLOBAL_CB_NODE *cb_node) { 434251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour bool skip_call = false; 434351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 434451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour skip_call |= ValidateOrIncrementBoundObjects(dev_data, cb_node, false); 434551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour // TODO : We should be able to remove the NULL look-up checks from the code below as long as 434651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour // all the corresponding cases are verified to cause CB_INVALID state and the CB_INVALID state 434751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour // should then be flagged prior to calling this function 434851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour for (auto drawDataElement : cb_node->drawData) { 434951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour for (auto buffer : drawDataElement.buffers) { 435051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour auto buffer_state = GetBufferState(dev_data, buffer); 435151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (!buffer_state) { 435251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, 435351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour (uint64_t)(buffer), __LINE__, DRAWSTATE_INVALID_BUFFER, "DS", 435451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour "Cannot submit cmd buffer using deleted buffer 0x%" PRIx64 ".", (uint64_t)(buffer)); 435551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 435651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 435751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 435851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour return skip_call; 435951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour} 436051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 43617bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski// Validate that queueFamilyIndices of primary command buffers match this queue 43627bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski// Secondary command buffers were previously validated in vkCmdExecuteCommands(). 43637bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinskistatic bool validateQueueFamilyIndices(layer_data *dev_data, GLOBAL_CB_NODE *pCB, VkQueue queue) { 43647bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski bool skip_call = false; 43659a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pPool = GetCommandPoolNode(dev_data, pCB->createInfo.commandPool); 43669a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto queue_state = GetQueueState(dev_data, queue); 43677bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski 436836c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlis if (pPool && queue_state && (pPool->queueFamilyIndex != queue_state->queueFamilyIndex)) { 43697bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 4370f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen reinterpret_cast<uint64_t>(pCB->commandBuffer), __LINE__, VALIDATION_ERROR_00139, "DS", 4371f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen "vkQueueSubmit: Primary command buffer 0x%p created in queue family %d is being submitted on queue " 4372f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen "0x%p from queue family %d. %s", 4373f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen pCB->commandBuffer, pPool->queueFamilyIndex, queue, queue_state->queueFamilyIndex, 4374f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen validation_error_map[VALIDATION_ERROR_00139]); 43757bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski } 43767bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski 43777bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski return skip_call; 43787bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski} 43797bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski 438051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourstatic bool validatePrimaryCommandBufferState(layer_data *dev_data, GLOBAL_CB_NODE *pCB, int current_submit_count) { 43815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Track in-use for resources off of primary and any secondary CBs 438283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 4383a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes 4384a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes // If USAGE_SIMULTANEOUS_USE_BIT not set then CB cannot already be executing 4385a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes // on device 438651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour skip_call |= validateCommandBufferSimultaneousUse(dev_data, pCB, current_submit_count); 4387a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes 438851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour skip_call |= validateResources(dev_data, pCB); 4389a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes 43905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!pCB->secondaryCommandBuffers.empty()) { 43915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto secondaryCmdBuffer : pCB->secondaryCommandBuffers) { 43929a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pSubCB = GetCBNode(dev_data, secondaryCmdBuffer); 439351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour skip_call |= validateResources(dev_data, pSubCB); 43944c665b29a9d2906a378417546c7fc6436731d07fTobin Ehlis if ((pSubCB->primaryCommandBuffer != pCB->commandBuffer) && 43954c665b29a9d2906a378417546c7fc6436731d07fTobin Ehlis !(pSubCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT)) { 4396f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen log_msg( 4397f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, 4398f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen __LINE__, VALIDATION_ERROR_00135, "DS", 4399f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen "Commandbuffer 0x%p was submitted with secondary buffer 0x%p but that buffer has subsequently been bound to " 4400f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen "primary cmd buffer 0x%p and it does not have VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT set. %s", 4401f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen pCB->commandBuffer, secondaryCmdBuffer, pSubCB->primaryCommandBuffer, 4402f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen validation_error_map[VALIDATION_ERROR_00135]); 44035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 44045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 44055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 4406a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes 440751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour skip_call |= validateCommandBufferState(dev_data, pCB, "vkQueueSubmit()", current_submit_count); 4408a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes 440983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis return skip_call; 44105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 44115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4412bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic bool ValidateFenceForSubmit(layer_data *dev_data, FENCE_NODE *pFence) { 441383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 441481c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes 4415651d92815dfff917308137bb67aacccc4f60df86Chris Forbes if (pFence) { 4416cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes if (pFence->state == FENCE_INFLIGHT) { 4417f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen // TODO: opportunities for VALIDATION_ERROR_00127, VALIDATION_ERROR_01647, VALIDATION_ERROR_01953 441883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, 441983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis (uint64_t)(pFence->fence), __LINE__, DRAWSTATE_INVALID_FENCE, "DS", 442083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis "Fence 0x%" PRIx64 " is already in use by another submission.", (uint64_t)(pFence->fence)); 4421a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis } 442281c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes 4423cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes else if (pFence->state == FENCE_RETIRED) { 4424f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen // TODO: opportunities for VALIDATION_ERROR_00126, VALIDATION_ERROR_01646, VALIDATION_ERROR_01953 442583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= 442683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, 442783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis reinterpret_cast<uint64_t &>(pFence->fence), __LINE__, MEMTRACK_INVALID_FENCE_STATE, "MEM", 442883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis "Fence 0x%" PRIxLEAST64 " submitted in SIGNALED state. Fences must be reset before being submitted", 442983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis reinterpret_cast<uint64_t &>(pFence->fence)); 4430a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis } 44315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 443281c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes 443383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis return skip_call; 443481c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes} 443581c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes 443651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourstatic void PostCallRecordQueueSubmit(layer_data *dev_data, VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, 443751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour VkFence fence) { 44389a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pQueue = GetQueueState(dev_data, queue); 44399a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pFence = GetFenceNode(dev_data, fence); 4440d7d60cccc862fee2d0b3ad410c5fdcc40ddc83aeChris Forbes 4441651d92815dfff917308137bb67aacccc4f60df86Chris Forbes // Mark the fence in-use. 4442651d92815dfff917308137bb67aacccc4f60df86Chris Forbes if (pFence) { 44439867daedbf52debc77d6568162ee21e071699b80Chris Forbes SubmitFence(pQueue, pFence, std::max(1u, submitCount)); 4444651d92815dfff917308137bb67aacccc4f60df86Chris Forbes } 4445651d92815dfff917308137bb67aacccc4f60df86Chris Forbes 444651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour // Now process each individual submit 44475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) { 444851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour std::vector<VkCommandBuffer> cbs; 44495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkSubmitInfo *submit = &pSubmits[submit_idx]; 44509867daedbf52debc77d6568162ee21e071699b80Chris Forbes vector<SEMAPHORE_WAIT> semaphore_waits; 44519867daedbf52debc77d6568162ee21e071699b80Chris Forbes vector<VkSemaphore> semaphore_signals; 44525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < submit->waitSemaphoreCount; ++i) { 445351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour VkSemaphore semaphore = submit->pWaitSemaphores[i]; 445451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour auto pSemaphore = GetSemaphoreNode(dev_data, semaphore); 445551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (pSemaphore) { 445651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (pSemaphore->signaler.first != VK_NULL_HANDLE) { 445751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour semaphore_waits.push_back({semaphore, pSemaphore->signaler.first, pSemaphore->signaler.second}); 445851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pSemaphore->in_use.fetch_add(1); 445951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 446051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pSemaphore->signaler.first = VK_NULL_HANDLE; 446151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pSemaphore->signaled = false; 446251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 446351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 446451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour for (uint32_t i = 0; i < submit->signalSemaphoreCount; ++i) { 446551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour VkSemaphore semaphore = submit->pSignalSemaphores[i]; 446651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour auto pSemaphore = GetSemaphoreNode(dev_data, semaphore); 446751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (pSemaphore) { 446851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pSemaphore->signaler.first = queue; 446951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pSemaphore->signaler.second = pQueue->seq + pQueue->submissions.size() + 1; 447051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pSemaphore->signaled = true; 447151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pSemaphore->in_use.fetch_add(1); 447251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour semaphore_signals.push_back(semaphore); 447351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 447451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 447551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour for (uint32_t i = 0; i < submit->commandBufferCount; i++) { 447651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour auto cb_node = GetCBNode(dev_data, submit->pCommandBuffers[i]); 447751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (cb_node) { 447851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour cbs.push_back(submit->pCommandBuffers[i]); 447951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour for (auto secondaryCmdBuffer : cb_node->secondaryCommandBuffers) { 448051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour cbs.push_back(secondaryCmdBuffer); 448151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 448251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour UpdateCmdBufImageLayouts(dev_data, cb_node); 448351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour incrementResources(dev_data, cb_node); 448451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (!cb_node->secondaryCommandBuffers.empty()) { 448551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour for (auto secondaryCmdBuffer : cb_node->secondaryCommandBuffers) { 448651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour GLOBAL_CB_NODE *pSubCB = GetCBNode(dev_data, secondaryCmdBuffer); 448751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour incrementResources(dev_data, pSubCB); 448851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 448951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 449051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 449151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 449251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pQueue->submissions.emplace_back(cbs, semaphore_waits, semaphore_signals, 449351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour submit_idx == submitCount - 1 ? fence : VK_NULL_HANDLE); 449451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 449551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 449651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (pFence && !submitCount) { 449751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour // If no submissions, but just dropping a fence on the end of the queue, 449851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour // record an empty submission with just the fence, so we can determine 449951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour // its completion. 450051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pQueue->submissions.emplace_back(std::vector<VkCommandBuffer>(), std::vector<SEMAPHORE_WAIT>(), std::vector<VkSemaphore>(), 450151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour fence); 450251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 450351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour} 450451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 450551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourstatic bool PreCallValidateQueueSubmit(layer_data *dev_data, VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, 450651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour VkFence fence) { 450751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour auto pFence = GetFenceNode(dev_data, fence); 450851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour bool skip_call = ValidateFenceForSubmit(dev_data, pFence); 450951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (skip_call) { 451051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour return true; 451151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 451251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 451351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour unordered_set<VkSemaphore> signaled_semaphores; 451451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour unordered_set<VkSemaphore> unsignaled_semaphores; 451551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour vector<VkCommandBuffer> current_cmds; 451651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour unordered_map<ImageSubresourcePair, IMAGE_LAYOUT_NODE> localImageLayoutMap = dev_data->imageLayoutMap; 451751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour // Now verify each individual submit 451851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) { 451951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour const VkSubmitInfo *submit = &pSubmits[submit_idx]; 452051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour for (uint32_t i = 0; i < submit->waitSemaphoreCount; ++i) { 4521208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis skip_call |= ValidateStageMaskGsTsEnables(dev_data, submit->pWaitDstStageMask[i], "vkQueueSubmit()", 4522208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis VALIDATION_ERROR_00142, VALIDATION_ERROR_00143); 452301a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes VkSemaphore semaphore = submit->pWaitSemaphores[i]; 45249a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pSemaphore = GetSemaphoreNode(dev_data, semaphore); 452501a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes if (pSemaphore) { 452651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (unsignaled_semaphores.count(semaphore) || 4527440bdd357701497c3442e3515f12ac1cfffc180aTony Barbour (!(signaled_semaphores.count(semaphore)) && !(pSemaphore->signaled))) { 452883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= 45291344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT, 45301344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis reinterpret_cast<const uint64_t &>(semaphore), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS", 4531226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "Queue 0x%p is waiting on semaphore 0x%" PRIx64 " that has no way to be signaled.", queue, 4532226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis reinterpret_cast<const uint64_t &>(semaphore)); 453351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } else { 453451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour signaled_semaphores.erase(semaphore); 453551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour unsignaled_semaphores.insert(semaphore); 45361344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis } 45375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 45385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 45395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < submit->signalSemaphoreCount; ++i) { 454001a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes VkSemaphore semaphore = submit->pSignalSemaphores[i]; 45419a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pSemaphore = GetSemaphoreNode(dev_data, semaphore); 454201a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes if (pSemaphore) { 4543440bdd357701497c3442e3515f12ac1cfffc180aTony Barbour if (signaled_semaphores.count(semaphore) || (!(unsignaled_semaphores.count(semaphore)) && pSemaphore->signaled)) { 454483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= 45451344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT, 45461344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis reinterpret_cast<const uint64_t &>(semaphore), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS", 4547226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "Queue 0x%p is signaling semaphore 0x%" PRIx64 4548414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller " that has already been signaled but not waited on by queue 0x%" PRIx64 ".", 4549226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis queue, reinterpret_cast<const uint64_t &>(semaphore), 45509867daedbf52debc77d6568162ee21e071699b80Chris Forbes reinterpret_cast<uint64_t &>(pSemaphore->signaler.first)); 45511344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis } else { 455251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour unsignaled_semaphores.erase(semaphore); 455351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour signaled_semaphores.insert(semaphore); 45541344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis } 45550a32ed7bdf03e7bda914e03c0bfa6ebf400cdf5bMichael Lentine } 45565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 45575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < submit->commandBufferCount; i++) { 45589a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, submit->pCommandBuffers[i]); 455951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour skip_call |= ValidateCmdBufImageLayouts(dev_data, cb_node, localImageLayoutMap); 4560d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis if (cb_node) { 456151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour current_cmds.push_back(submit->pCommandBuffers[i]); 456251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour skip_call |= validatePrimaryCommandBufferState( 456351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour dev_data, cb_node, (int)std::count(current_cmds.begin(), current_cmds.end(), submit->pCommandBuffers[i])); 4564d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis skip_call |= validateQueueFamilyIndices(dev_data, cb_node, queue); 456551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 4566ea371fa7c8c57edb4d1436e4570cf54f3fc0463fTobin Ehlis // Potential early exit here as bad object state may crash in delayed function calls 456751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (skip_call) { 456851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour return true; 456951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 457051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 45711344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis // Call submit-time functions to validate/update state 4572d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis for (auto &function : cb_node->validate_functions) { 457383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= function(); 45741344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis } 4575d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis for (auto &function : cb_node->eventUpdates) { 457683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= function(queue); 45771344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis } 4578d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis for (auto &function : cb_node->queryUpdates) { 457983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= function(queue); 4580d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 45811344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis } 45825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 45839867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 458451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour return skip_call; 458551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour} 45869867daedbf52debc77d6568162ee21e071699b80Chris Forbes 458751920949f887ce8d3666c73c28ff19a5d8325a37Tony BarbourVKAPI_ATTR VkResult VKAPI_CALL QueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence) { 458851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map); 458951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour std::unique_lock<std::mutex> lock(global_lock); 459051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 459151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour bool skip = PreCallValidateQueueSubmit(dev_data, queue, submitCount, pSubmits, fence); 4592b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 45935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4594440bdd357701497c3442e3515f12ac1cfffc180aTony Barbour if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 459551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 459651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour VkResult result = dev_data->dispatch_table.QueueSubmit(queue, submitCount, pSubmits, fence); 459751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 459851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour lock.lock(); 459951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour PostCallRecordQueueSubmit(dev_data, queue, submitCount, pSubmits, fence); 460051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour lock.unlock(); 46015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 46025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 46035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4604f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultzstatic bool PreCallValidateAllocateMemory(layer_data *dev_data) { 4605f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz bool skip = false; 4606f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz if (dev_data->memObjMap.size() >= dev_data->phys_dev_properties.properties.limits.maxMemoryAllocationCount) { 4607f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 4608f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz reinterpret_cast<const uint64_t &>(dev_data->device), __LINE__, VALIDATION_ERROR_00611, "MEM", 4609f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz "Number of currently valid memory objects is not less than the maximum allowed (%u). %s", 4610f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz dev_data->phys_dev_properties.properties.limits.maxMemoryAllocationCount, 4611f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz validation_error_map[VALIDATION_ERROR_00611]); 4612f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz } 4613f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz return skip; 4614f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz} 4615f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz 4616f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultzstatic void PostCallRecordAllocateMemory(layer_data *dev_data, const VkMemoryAllocateInfo *pAllocateInfo, VkDeviceMemory *pMemory) { 4617f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz add_mem_obj_info(dev_data, dev_data->device, *pMemory, pAllocateInfo); 4618f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz return; 4619f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz} 4620f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz 462189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL AllocateMemory(VkDevice device, const VkMemoryAllocateInfo *pAllocateInfo, 462289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkDeviceMemory *pMemory) { 4623f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 462456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 4625f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz std::unique_lock<std::mutex> lock(global_lock); 4626f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz bool skip = PreCallValidateAllocateMemory(dev_data); 4627f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz if (!skip) { 4628f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz lock.unlock(); 4629f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz result = dev_data->dispatch_table.AllocateMemory(device, pAllocateInfo, pAllocator, pMemory); 4630f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz lock.lock(); 4631f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz if (VK_SUCCESS == result) { 4632f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz PostCallRecordAllocateMemory(dev_data, pAllocateInfo, pMemory); 4633f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz } 4634e12739a56d02ca2fb5f0273862668e7475a21a6cMark Lobodzinski } 46355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 46365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 46375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4638177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis// For given obj node, if it is use, flag a validation error and return callback result, else return false 4639177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlisbool ValidateObjectNotInUse(const layer_data *dev_data, BASE_NODE *obj_node, VK_OBJECT obj_struct, 4640177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis UNIQUE_VALIDATION_ERROR_CODE error_code) { 4641cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.object_in_use) return false; 4642177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis bool skip = false; 4643177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis if (obj_node->in_use.load()) { 4644177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, obj_struct.type, obj_struct.handle, __LINE__, 4645177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis error_code, "DS", "Cannot delete %s 0x%" PRIx64 " that is currently in use by a command buffer. %s", 4646177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis object_type_to_string(obj_struct.type), obj_struct.handle, validation_error_map[error_code]); 4647177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis } 4648177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis return skip; 4649177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis} 46505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4651177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlisstatic bool PreCallValidateFreeMemory(layer_data *dev_data, VkDeviceMemory mem, DEVICE_MEM_INFO **mem_info, VK_OBJECT *obj_struct) { 46529a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *mem_info = GetMemObjInfo(dev_data, mem); 465394165f5005d1fa37801d49067fe7751789b89d27Tobin Ehlis *obj_struct = {reinterpret_cast<uint64_t &>(mem), VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT}; 4654cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.free_memory) return false; 4655177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis bool skip = false; 4656177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis if (*mem_info) { 4657177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis skip |= ValidateObjectNotInUse(dev_data, *mem_info, *obj_struct, VALIDATION_ERROR_00620); 4658177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis } 4659177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis return skip; 4660177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis} 46615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4662177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlisstatic void PostCallRecordFreeMemory(layer_data *dev_data, VkDeviceMemory mem, DEVICE_MEM_INFO *mem_info, VK_OBJECT obj_struct) { 4663177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis // Clear mem binding for any bound objects 466447705d01140c9f1492885e6efc5fa262e7e1c6a0Tobin Ehlis for (auto obj : mem_info->obj_bindings) { 466547705d01140c9f1492885e6efc5fa262e7e1c6a0Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, obj.type, obj.handle, __LINE__, MEMTRACK_FREED_MEM_REF, 466647705d01140c9f1492885e6efc5fa262e7e1c6a0Tobin Ehlis "MEM", "VK Object 0x%" PRIxLEAST64 " still has a reference to mem obj 0x%" PRIxLEAST64, obj.handle, 466747705d01140c9f1492885e6efc5fa262e7e1c6a0Tobin Ehlis (uint64_t)mem_info->mem); 466847705d01140c9f1492885e6efc5fa262e7e1c6a0Tobin Ehlis switch (obj.type) { 4669cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT: { 46709a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_state = GetImageState(dev_data, reinterpret_cast<VkImage &>(obj.handle)); 4671cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski assert(image_state); // Any destroyed images should already be removed from bindings 4672cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski image_state->binding.mem = MEMORY_UNBOUND; 4673cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 4674cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 4675cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT: { 46769a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto buffer_state = GetBufferState(dev_data, reinterpret_cast<VkBuffer &>(obj.handle)); 4677cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski assert(buffer_state); // Any destroyed buffers should already be removed from bindings 4678cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski buffer_state->binding.mem = MEMORY_UNBOUND; 4679cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 4680cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 4681cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 4682cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Should only have buffer or image objects bound to memory 4683cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski assert(0); 4684177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis } 4685177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis } 4686177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis // Any bound cmd buffers are now invalid 468739c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis invalidateCommandBuffers(dev_data, mem_info->cb_bindings, obj_struct); 4688177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis dev_data->memObjMap.erase(mem); 4689177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis} 4690177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis 4691177063aac84fac6f4e650c2629a08b48be643f96Tobin EhlisVKAPI_ATTR void VKAPI_CALL FreeMemory(VkDevice device, VkDeviceMemory mem, const VkAllocationCallbacks *pAllocator) { 469256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 4693177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis DEVICE_MEM_INFO *mem_info = nullptr; 4694177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis VK_OBJECT obj_struct; 4695b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 4696177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis bool skip = PreCallValidateFreeMemory(dev_data, mem, &mem_info, &obj_struct); 4697177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis if (!skip) { 4698177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis lock.unlock(); 4699177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis dev_data->dispatch_table.FreeMemory(device, mem, pAllocator); 4700177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis lock.lock(); 4701405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (mem != VK_NULL_HANDLE) { 4702405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordFreeMemory(dev_data, mem, mem_info, obj_struct); 4703405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 470474243a735fe102b370237ddf80d3e6f7ec5246dbMark Mueller } 47055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 47065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4707f57fc64ac43691ad98e1713886b345465573070aTobin Ehlis// Validate that given Map memory range is valid. This means that the memory should not already be mapped, 4708f57fc64ac43691ad98e1713886b345465573070aTobin Ehlis// and that the size of the map range should be: 4709f57fc64ac43691ad98e1713886b345465573070aTobin Ehlis// 1. Not zero 4710f57fc64ac43691ad98e1713886b345465573070aTobin Ehlis// 2. Within the size of the memory allocation 471151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool ValidateMapMemRange(layer_data *dev_data, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size) { 471283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 47135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 47145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (size == 0) { 471551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 471683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis (uint64_t)mem, __LINE__, MEMTRACK_INVALID_MAP, "MEM", 471783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis "VkMapMemory: Attempting to map memory range of size zero"); 47185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 47195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 472051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis auto mem_element = dev_data->memObjMap.find(mem); 472151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (mem_element != dev_data->memObjMap.end()) { 472257fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis auto mem_info = mem_element->second.get(); 47235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // It is an application error to call VkMapMemory on an object that is already mapped 4724de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis if (mem_info->mem_range.size != 0) { 472551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 472683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis (uint64_t)mem, __LINE__, MEMTRACK_INVALID_MAP, "MEM", 472783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis "VkMapMemory: Attempting to map memory on an already-mapped object 0x%" PRIxLEAST64, (uint64_t)mem); 47285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 47295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 47305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Validate that offset + size is within object's allocationSize 47315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (size == VK_WHOLE_SIZE) { 4732de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis if (offset >= mem_info->alloc_info.allocationSize) { 473351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call = 473451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 473551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis (uint64_t)mem, __LINE__, MEMTRACK_INVALID_MAP, "MEM", 473651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis "Mapping Memory from 0x%" PRIx64 " to 0x%" PRIx64 473751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis " with size of VK_WHOLE_SIZE oversteps total array size 0x%" PRIx64, 473851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis offset, mem_info->alloc_info.allocationSize, mem_info->alloc_info.allocationSize); 47395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 47405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 4741de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis if ((offset + size) > mem_info->alloc_info.allocationSize) { 4742f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen skip_call = log_msg( 474351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 4744f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen (uint64_t)mem, __LINE__, VALIDATION_ERROR_00628, "MEM", 4745f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen "Mapping Memory from 0x%" PRIx64 " to 0x%" PRIx64 " oversteps total array size 0x%" PRIx64 ". %s", offset, 4746f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen size + offset, mem_info->alloc_info.allocationSize, validation_error_map[VALIDATION_ERROR_00628]); 47475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 47485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 47495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 475083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis return skip_call; 47515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 47525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 475351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic void storeMemRanges(layer_data *dev_data, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size) { 47549a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto mem_info = GetMemObjInfo(dev_data, mem); 475557fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis if (mem_info) { 4756de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis mem_info->mem_range.offset = offset; 4757de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis mem_info->mem_range.size = size; 47585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 47595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 47605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 476151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool deleteMemRanges(layer_data *dev_data, VkDeviceMemory mem) { 476283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 47639a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto mem_info = GetMemObjInfo(dev_data, mem); 476457fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis if (mem_info) { 4765de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis if (!mem_info->mem_range.size) { 47665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Valid Usage: memory must currently be mapped 476751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 4768f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen (uint64_t)mem, __LINE__, VALIDATION_ERROR_00649, "MEM", 4769f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen "Unmapping Memory without memory being mapped: mem obj 0x%" PRIxLEAST64 ". %s", (uint64_t)mem, 4770f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen validation_error_map[VALIDATION_ERROR_00649]); 47715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 4772de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis mem_info->mem_range.size = 0; 47735f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski if (mem_info->shadow_copy) { 47745f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski free(mem_info->shadow_copy_base); 47755f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski mem_info->shadow_copy_base = 0; 47765f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski mem_info->shadow_copy = 0; 47775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 47785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 477983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis return skip_call; 47805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 47815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 47825f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski// Guard value for pad data 47835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic char NoncoherentMemoryFillValue = 0xb; 47845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 47855f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinskistatic void initializeAndTrackMemory(layer_data *dev_data, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size, 47865f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski void **ppData) { 47879a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto mem_info = GetMemObjInfo(dev_data, mem); 478857fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis if (mem_info) { 4789de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis mem_info->p_driver_data = *ppData; 4790de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis uint32_t index = mem_info->alloc_info.memoryTypeIndex; 4791b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis if (dev_data->phys_dev_mem_props.memoryTypes[index].propertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) { 47925f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski mem_info->shadow_copy = 0; 47935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 47945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (size == VK_WHOLE_SIZE) { 47955f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski size = mem_info->alloc_info.allocationSize - offset; 47965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 47975f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski mem_info->shadow_pad_size = dev_data->phys_dev_properties.properties.limits.minMemoryMapAlignment; 47985f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski assert(vk_safe_modulo(mem_info->shadow_pad_size, 47995f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski dev_data->phys_dev_properties.properties.limits.minMemoryMapAlignment) == 0); 48005f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski // Ensure start of mapped region reflects hardware alignment constraints 48015f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski uint64_t map_alignment = dev_data->phys_dev_properties.properties.limits.minMemoryMapAlignment; 48025f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski 48035f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski // From spec: (ppData - offset) must be aligned to at least limits::minMemoryMapAlignment. 48045f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski uint64_t start_offset = offset % map_alignment; 48055f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski // Data passed to driver will be wrapped by a guardband of data to detect over- or under-writes. 4806bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski mem_info->shadow_copy_base = 4807bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski malloc(static_cast<size_t>(2 * mem_info->shadow_pad_size + size + map_alignment + start_offset)); 48085f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski 48095f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski mem_info->shadow_copy = 48105f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski reinterpret_cast<char *>((reinterpret_cast<uintptr_t>(mem_info->shadow_copy_base) + map_alignment) & 4811bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski ~(map_alignment - 1)) + 4812bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski start_offset; 48135f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski assert(vk_safe_modulo(reinterpret_cast<uintptr_t>(mem_info->shadow_copy) + mem_info->shadow_pad_size - start_offset, 48145f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski map_alignment) == 0); 48155f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski 48166e17c244b21ce43ac57404a00a0d844039eed363Mark Lobodzinski memset(mem_info->shadow_copy, NoncoherentMemoryFillValue, static_cast<size_t>(2 * mem_info->shadow_pad_size + size)); 48175f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski *ppData = static_cast<char *>(mem_info->shadow_copy) + mem_info->shadow_pad_size; 48185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 48195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 48205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 48215f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski 4822a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis// Verify that state for fence being waited on is appropriate. That is, 48239867daedbf52debc77d6568162ee21e071699b80Chris Forbes// a fence being waited on should not already be signaled and 4824a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis// it should have been submitted on a queue or during acquire next image 482549f6132af865afd5b7f413c91125971ac97c135aChris Forbesstatic inline bool verifyWaitFenceState(layer_data *dev_data, VkFence fence, const char *apiCall) { 482683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 48279b48b44dd917f95b5f34dd629ec4076fc87eb3a2Chris Forbes 48289a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pFence = GetFenceNode(dev_data, fence); 48299b48b44dd917f95b5f34dd629ec4076fc87eb3a2Chris Forbes if (pFence) { 4830cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes if (pFence->state == FENCE_UNSIGNALED) { 483183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, 483283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis reinterpret_cast<uint64_t &>(fence), __LINE__, MEMTRACK_INVALID_FENCE_STATE, "MEM", 4833cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s called for fence 0x%" PRIxLEAST64 4834cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " which has not been submitted on a Queue or during " 483583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis "acquire next image.", 483683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis apiCall, reinterpret_cast<uint64_t &>(fence)); 48375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 48385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 483983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis return skip_call; 48405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 4841a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis 4842b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlisstatic void RetireFence(layer_data *dev_data, VkFence fence) { 48439a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pFence = GetFenceNode(dev_data, fence); 4844b3ecd4c1fb44a2e65dfc13256afa9150aabde1d4Chris Forbes if (pFence->signaler.first != VK_NULL_HANDLE) { 484525002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Fence signaller is a queue -- use this as proof that prior operations on that queue have completed. 48469a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis RetireWorkOnQueue(dev_data, GetQueueState(dev_data, pFence->signaler.first), pFence->signaler.second); 4847bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski } else { 484825002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Fence signaller is the WSI. We're not tracking what the WSI op actually /was/ in CV yet, but we need to mark 484925002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // the fence as retired. 4850d4513979120463171eb479cdded9336eb9944da1Chris Forbes pFence->state = FENCE_RETIRED; 4851d4513979120463171eb479cdded9336eb9944da1Chris Forbes } 4852b3ecd4c1fb44a2e65dfc13256afa9150aabde1d4Chris Forbes} 4853b3ecd4c1fb44a2e65dfc13256afa9150aabde1d4Chris Forbes 4854accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlisstatic bool PreCallValidateWaitForFences(layer_data *dev_data, uint32_t fence_count, const VkFence *fences) { 4855cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.wait_for_fences) return false; 4856accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis bool skip = false; 4857accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis for (uint32_t i = 0; i < fence_count; i++) { 4858accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis skip |= verifyWaitFenceState(dev_data, fences[i], "vkWaitForFences"); 4859b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis skip |= VerifyQueueStateToFence(dev_data, fences[i]); 4860accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis } 4861accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis return skip; 4862accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis} 4863accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis 4864b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlisstatic void PostCallRecordWaitForFences(layer_data *dev_data, uint32_t fence_count, const VkFence *fences, VkBool32 wait_all) { 4865b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis // When we know that all fences are complete we can clean/remove their CBs 4866accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis if ((VK_TRUE == wait_all) || (1 == fence_count)) { 4867accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis for (uint32_t i = 0; i < fence_count; i++) { 4868b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis RetireFence(dev_data, fences[i]); 4869accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis } 4870accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis } 4871accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis // NOTE : Alternate case not handled here is when some fences have completed. In 4872accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis // this case for app to guarantee which fences completed it will have to call 4873b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis // vkGetFenceStatus() at which point we'll clean/remove their CBs if complete. 4874accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis} 4875accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis 4876bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL WaitForFences(VkDevice device, uint32_t fenceCount, const VkFence *pFences, VkBool32 waitAll, 4877bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski uint64_t timeout) { 487856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 48795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Verify fence status of submitted fences 4880b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 4881accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis bool skip = PreCallValidateWaitForFences(dev_data, fenceCount, pFences); 4882b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 4883cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 4884a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis 48854a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.WaitForFences(device, fenceCount, pFences, waitAll, timeout); 4886414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller 48875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (result == VK_SUCCESS) { 4888b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.lock(); 4889b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis PostCallRecordWaitForFences(dev_data, fenceCount, pFences, waitAll); 4890b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 48915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 48925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 48935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 48945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4895f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlisstatic bool PreCallValidateGetFenceStatus(layer_data *dev_data, VkFence fence) { 4896cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.get_fence_state) return false; 4897f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis return verifyWaitFenceState(dev_data, fence, "vkGetFenceStatus"); 4898f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis} 4899f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis 4900b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlisstatic void PostCallRecordGetFenceStatus(layer_data *dev_data, VkFence fence) { RetireFence(dev_data, fence); } 4901f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis 490289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL GetFenceStatus(VkDevice device, VkFence fence) { 490356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 4904b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 4905f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis bool skip = PreCallValidateGetFenceStatus(dev_data, fence); 4906b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 4907cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 4908a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis 49094a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.GetFenceStatus(device, fence); 49105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (result == VK_SUCCESS) { 4911f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis lock.lock(); 4912b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis PostCallRecordGetFenceStatus(dev_data, fence); 4913f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis lock.unlock(); 49145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 49155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 49165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 49175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 49183b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlisstatic void PostCallRecordGetDeviceQueue(layer_data *dev_data, uint32_t q_family_index, VkQueue queue) { 49193b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis // Add queue to tracking set only if it is new 49203b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis auto result = dev_data->queues.emplace(queue); 49213b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis if (result.second == true) { 492236c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlis QUEUE_STATE *queue_state = &dev_data->queueMap[queue]; 49233b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis queue_state->queue = queue; 49243b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis queue_state->queueFamilyIndex = q_family_index; 49253b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis queue_state->seq = 0; 49263b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis } 49273b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis} 49283b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis 4929bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL GetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue *pQueue) { 493056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 49314a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue); 4932b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 4933b376edacad6f7ab3fcc0a914e9b1673a9fcd5143Mark Lobodzinski 49343b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis PostCallRecordGetDeviceQueue(dev_data, queueFamilyIndex, *pQueue); 49355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 49365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 493736c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlisstatic bool PreCallValidateQueueWaitIdle(layer_data *dev_data, VkQueue queue, QUEUE_STATE **queue_state) { 49389a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *queue_state = GetQueueState(dev_data, queue); 4939cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.queue_wait_idle) return false; 4940e0cec9ec6dd3cfd83345cabba55ec021681801dbTobin Ehlis return VerifyQueueStateToSeq(dev_data, *queue_state, (*queue_state)->seq + (*queue_state)->submissions.size()); 49414273a1c157585a645dca4c960086032793899d05Tobin Ehlis} 49424273a1c157585a645dca4c960086032793899d05Tobin Ehlis 494336c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlisstatic void PostCallRecordQueueWaitIdle(layer_data *dev_data, QUEUE_STATE *queue_state) { 4944e0cec9ec6dd3cfd83345cabba55ec021681801dbTobin Ehlis RetireWorkOnQueue(dev_data, queue_state, queue_state->seq + queue_state->submissions.size()); 49454273a1c157585a645dca4c960086032793899d05Tobin Ehlis} 49464273a1c157585a645dca4c960086032793899d05Tobin Ehlis 494789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL QueueWaitIdle(VkQueue queue) { 494856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map); 494936c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlis QUEUE_STATE *queue_state = nullptr; 49509867daedbf52debc77d6568162ee21e071699b80Chris Forbes std::unique_lock<std::mutex> lock(global_lock); 49514273a1c157585a645dca4c960086032793899d05Tobin Ehlis bool skip = PreCallValidateQueueWaitIdle(dev_data, queue, &queue_state); 49529867daedbf52debc77d6568162ee21e071699b80Chris Forbes lock.unlock(); 4953cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 49544a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.QueueWaitIdle(queue); 49554273a1c157585a645dca4c960086032793899d05Tobin Ehlis if (VK_SUCCESS == result) { 4956e0cec9ec6dd3cfd83345cabba55ec021681801dbTobin Ehlis lock.lock(); 4957e0cec9ec6dd3cfd83345cabba55ec021681801dbTobin Ehlis PostCallRecordQueueWaitIdle(dev_data, queue_state); 4958e0cec9ec6dd3cfd83345cabba55ec021681801dbTobin Ehlis lock.unlock(); 49594273a1c157585a645dca4c960086032793899d05Tobin Ehlis } 49605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 49615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 49625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 49638767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlisstatic bool PreCallValidateDeviceWaitIdle(layer_data *dev_data) { 4964cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.device_wait_idle) return false; 49658767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis bool skip = false; 49668767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis for (auto &queue : dev_data->queueMap) { 49678767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis skip |= VerifyQueueStateToSeq(dev_data, &queue.second, queue.second.seq + queue.second.submissions.size()); 49688767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis } 49698767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis return skip; 49708767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis} 49718767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis 49728767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlisstatic void PostCallRecordDeviceWaitIdle(layer_data *dev_data) { 49738767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis for (auto &queue : dev_data->queueMap) { 49748767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis RetireWorkOnQueue(dev_data, &queue.second, queue.second.seq + queue.second.submissions.size()); 49758767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis } 49768767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis} 49778767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis 497889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL DeviceWaitIdle(VkDevice device) { 497956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 4980b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 49818767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis bool skip = PreCallValidateDeviceWaitIdle(dev_data); 4982b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 4983cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 49844a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.DeviceWaitIdle(device); 49858767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis if (VK_SUCCESS == result) { 49868767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis lock.lock(); 49878767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis PostCallRecordDeviceWaitIdle(dev_data); 49888767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis lock.unlock(); 49898767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis } 49905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 49915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 49925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 49931d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlisstatic bool PreCallValidateDestroyFence(layer_data *dev_data, VkFence fence, FENCE_NODE **fence_node, VK_OBJECT *obj_struct) { 49949a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *fence_node = GetFenceNode(dev_data, fence); 49951d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis *obj_struct = {reinterpret_cast<uint64_t &>(fence), VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT}; 4996cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_fence) return false; 49971d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis bool skip = false; 49981d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis if (*fence_node) { 49991d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis if ((*fence_node)->state == FENCE_INFLIGHT) { 50001d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, 5001208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis (uint64_t)(fence), __LINE__, VALIDATION_ERROR_00173, "DS", "Fence 0x%" PRIx64 " is in use. %s", 5002208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis (uint64_t)(fence), validation_error_map[VALIDATION_ERROR_00173]); 50031d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis } 50041d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis } 50051d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis return skip; 50061d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis} 50071d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis 50081d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlisstatic void PostCallRecordDestroyFence(layer_data *dev_data, VkFence fence) { dev_data->fenceMap.erase(fence); } 50091d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis 501089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL DestroyFence(VkDevice device, VkFence fence, const VkAllocationCallbacks *pAllocator) { 501156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 50121d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis // Common data objects used pre & post call 50131d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis FENCE_NODE *fence_node = nullptr; 50141d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis VK_OBJECT obj_struct; 5015b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 50161d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis bool skip = PreCallValidateDestroyFence(dev_data, fence, &fence_node, &obj_struct); 50171344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis 50181d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis if (!skip) { 50191d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis lock.unlock(); 50204a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyFence(device, fence, pAllocator); 50211d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis lock.lock(); 50221d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis PostCallRecordDestroyFence(dev_data, fence); 50231d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis } 50245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 50255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5026c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlisstatic bool PreCallValidateDestroySemaphore(layer_data *dev_data, VkSemaphore semaphore, SEMAPHORE_NODE **sema_node, 5027c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis VK_OBJECT *obj_struct) { 50289a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *sema_node = GetSemaphoreNode(dev_data, semaphore); 5029c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis *obj_struct = {reinterpret_cast<uint64_t &>(semaphore), VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT}; 5030cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_semaphore) return false; 5031c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis bool skip = false; 5032c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis if (*sema_node) { 5033c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis skip |= ValidateObjectNotInUse(dev_data, *sema_node, *obj_struct, VALIDATION_ERROR_00199); 5034c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis } 5035c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis return skip; 5036c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis} 5037c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis 5038c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlisstatic void PostCallRecordDestroySemaphore(layer_data *dev_data, VkSemaphore sema) { dev_data->semaphoreMap.erase(sema); } 5039c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis 5040bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroySemaphore(VkDevice device, VkSemaphore semaphore, const VkAllocationCallbacks *pAllocator) { 504156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 5042c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis SEMAPHORE_NODE *sema_node; 5043c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis VK_OBJECT obj_struct; 5044e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 5045c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis bool skip = PreCallValidateDestroySemaphore(dev_data, semaphore, &sema_node, &obj_struct); 5046eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis if (!skip) { 5047eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis lock.unlock(); 50484a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroySemaphore(device, semaphore, pAllocator); 5049c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis lock.lock(); 5050c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis PostCallRecordDestroySemaphore(dev_data, semaphore); 505199d938c90c2f000ee73fb13513dacf84ffa5651fMark Mueller } 50525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 50535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 50544710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlisstatic bool PreCallValidateDestroyEvent(layer_data *dev_data, VkEvent event, EVENT_STATE **event_state, VK_OBJECT *obj_struct) { 50559a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *event_state = GetEventNode(dev_data, event); 505694165f5005d1fa37801d49067fe7751789b89d27Tobin Ehlis *obj_struct = {reinterpret_cast<uint64_t &>(event), VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT}; 5057cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_event) return false; 5058d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis bool skip = false; 5059d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis if (*event_state) { 5060d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis skip |= ValidateObjectNotInUse(dev_data, *event_state, *obj_struct, VALIDATION_ERROR_00213); 5061d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis } 5062d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis return skip; 5063d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis} 5064d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis 50654710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlisstatic void PostCallRecordDestroyEvent(layer_data *dev_data, VkEvent event, EVENT_STATE *event_state, VK_OBJECT obj_struct) { 506639c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis invalidateCommandBuffers(dev_data, event_state->cb_bindings, obj_struct); 5067d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis dev_data->eventMap.erase(event); 5068d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis} 5069d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis 507089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL DestroyEvent(VkDevice device, VkEvent event, const VkAllocationCallbacks *pAllocator) { 507156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 50724710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis EVENT_STATE *event_state = nullptr; 5073d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis VK_OBJECT obj_struct; 5074b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 5075d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis bool skip = PreCallValidateDestroyEvent(dev_data, event, &event_state, &obj_struct); 5076f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis if (!skip) { 5077f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis lock.unlock(); 50784a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyEvent(device, event, pAllocator); 5079d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis lock.lock(); 5080405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (event != VK_NULL_HANDLE) { 5081405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyEvent(dev_data, event, event_state, obj_struct); 5082405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 5083f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis } 50845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 50855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 508683c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlisstatic bool PreCallValidateDestroyQueryPool(layer_data *dev_data, VkQueryPool query_pool, QUERY_POOL_NODE **qp_state, 508783c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis VK_OBJECT *obj_struct) { 50889a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *qp_state = GetQueryPoolNode(dev_data, query_pool); 508983c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis *obj_struct = {reinterpret_cast<uint64_t &>(query_pool), VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT}; 5090cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_query_pool) return false; 509183c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis bool skip = false; 509283c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis if (*qp_state) { 509383c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis skip |= ValidateObjectNotInUse(dev_data, *qp_state, *obj_struct, VALIDATION_ERROR_01012); 509483c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis } 509583c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis return skip; 509683c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis} 509783c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis 5098bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic void PostCallRecordDestroyQueryPool(layer_data *dev_data, VkQueryPool query_pool, QUERY_POOL_NODE *qp_state, 5099bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VK_OBJECT obj_struct) { 510083c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis invalidateCommandBuffers(dev_data, qp_state->cb_bindings, obj_struct); 510183c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis dev_data->queryPoolMap.erase(query_pool); 510283c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis} 510383c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis 5104bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyQueryPool(VkDevice device, VkQueryPool queryPool, const VkAllocationCallbacks *pAllocator) { 510556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 510683c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis QUERY_POOL_NODE *qp_state = nullptr; 510783c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis VK_OBJECT obj_struct; 5108ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 510983c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis bool skip = PreCallValidateDestroyQueryPool(dev_data, queryPool, &qp_state, &obj_struct); 5110f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis if (!skip) { 5111f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis lock.unlock(); 51124a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyQueryPool(device, queryPool, pAllocator); 511383c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis lock.lock(); 5114405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (queryPool != VK_NULL_HANDLE) { 5115405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyQueryPool(dev_data, queryPool, qp_state, obj_struct); 5116405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 5117f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis } 51185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 51199fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlisstatic bool PreCallValidateGetQueryPoolResults(layer_data *dev_data, VkQueryPool query_pool, uint32_t first_query, 51209fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis uint32_t query_count, VkQueryResultFlags flags, 51219fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis unordered_map<QueryObject, vector<VkCommandBuffer>> *queries_in_flight) { 51229fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis for (auto cmd_buffer : dev_data->globalInFlightCmdBuffers) { 51239a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb = GetCBNode(dev_data, cmd_buffer); 51249fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis for (auto query_state_pair : cb->queryToStateMap) { 51259fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis (*queries_in_flight)[query_state_pair.first].push_back(cmd_buffer); 51265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 51275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5128cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.get_query_pool_results) return false; 51299fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis bool skip = false; 51309fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis for (uint32_t i = 0; i < query_count; ++i) { 51319fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis QueryObject query = {query_pool, first_query + i}; 51329fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis auto qif_pair = queries_in_flight->find(query); 51339fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis auto query_state_pair = dev_data->queryToStateMap.find(query); 51349fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis if (query_state_pair != dev_data->queryToStateMap.end()) { 5135ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski // Available and in flight 51369fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis if (qif_pair != queries_in_flight->end() && query_state_pair != dev_data->queryToStateMap.end() && 51379fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis query_state_pair->second) { 51389fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis for (auto cmd_buffer : qif_pair->second) { 51399a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb = GetCBNode(dev_data, cmd_buffer); 51409fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis auto query_event_pair = cb->waitedEventsBeforeQueryReset.find(query); 51419fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis if (query_event_pair == cb->waitedEventsBeforeQueryReset.end()) { 51429fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 51439fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, __LINE__, DRAWSTATE_INVALID_QUERY, "DS", 51449fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis "Cannot get query results on queryPool 0x%" PRIx64 " with index %d which is in flight.", 51459fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis (uint64_t)(query_pool), first_query + i); 5146ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski } 5147ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski } 5148ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski // Unavailable and in flight 51499fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis } else if (qif_pair != queries_in_flight->end() && query_state_pair != dev_data->queryToStateMap.end() && 51509fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis !query_state_pair->second) { 5151ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski // TODO : Can there be the same query in use by multiple command buffers in flight? 5152ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski bool make_available = false; 51539fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis for (auto cmd_buffer : qif_pair->second) { 51549a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb = GetCBNode(dev_data, cmd_buffer); 51559fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis make_available |= cb->queryToStateMap[query]; 5156ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski } 5157ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski if (!(((flags & VK_QUERY_RESULT_PARTIAL_BIT) || (flags & VK_QUERY_RESULT_WAIT_BIT)) && make_available)) { 51589fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 51599fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, __LINE__, DRAWSTATE_INVALID_QUERY, "DS", 51609fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis "Cannot get query results on queryPool 0x%" PRIx64 " with index %d which is unavailable.", 51619fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis (uint64_t)(query_pool), first_query + i); 51625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5163ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski // Unavailable 51649fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis } else if (query_state_pair != dev_data->queryToStateMap.end() && !query_state_pair->second) { 51659fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, 51669fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis __LINE__, DRAWSTATE_INVALID_QUERY, "DS", 51679fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis "Cannot get query results on queryPool 0x%" PRIx64 " with index %d which is unavailable.", 51689fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis (uint64_t)(query_pool), first_query + i); 51699fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis // Uninitialized 51709fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis } else if (query_state_pair == dev_data->queryToStateMap.end()) { 51719fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, 51729fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis __LINE__, DRAWSTATE_INVALID_QUERY, "DS", 51739fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis "Cannot get query results on queryPool 0x%" PRIx64 51749fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis " with index %d as data has not been collected for this index.", 51759fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis (uint64_t)(query_pool), first_query + i); 51765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 51775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 51785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 51799fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis return skip; 51809fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis} 51819fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis 51829fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlisstatic void PostCallRecordGetQueryPoolResults(layer_data *dev_data, VkQueryPool query_pool, uint32_t first_query, 51839fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis uint32_t query_count, 51849fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis unordered_map<QueryObject, vector<VkCommandBuffer>> *queries_in_flight) { 51859fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis for (uint32_t i = 0; i < query_count; ++i) { 51869fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis QueryObject query = {query_pool, first_query + i}; 51879fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis auto qif_pair = queries_in_flight->find(query); 51889fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis auto query_state_pair = dev_data->queryToStateMap.find(query); 51899fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis if (query_state_pair != dev_data->queryToStateMap.end()) { 51909fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis // Available and in flight 51919fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis if (qif_pair != queries_in_flight->end() && query_state_pair != dev_data->queryToStateMap.end() && 51929fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis query_state_pair->second) { 51939fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis for (auto cmd_buffer : qif_pair->second) { 51949a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb = GetCBNode(dev_data, cmd_buffer); 51959fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis auto query_event_pair = cb->waitedEventsBeforeQueryReset.find(query); 51969fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis if (query_event_pair != cb->waitedEventsBeforeQueryReset.end()) { 51979fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis for (auto event : query_event_pair->second) { 51989fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis dev_data->eventMap[event].needsSignaled = true; 51999fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis } 52009fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis } 52019fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis } 52029fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis } 52039fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis } 52049fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis } 52059fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis} 52069fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis 52079fdee42cd357379efb9aa27f90beb75d1f824955Tobin EhlisVKAPI_ATTR VkResult VKAPI_CALL GetQueryPoolResults(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, 52089fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis size_t dataSize, void *pData, VkDeviceSize stride, VkQueryResultFlags flags) { 520956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 52109fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis unordered_map<QueryObject, vector<VkCommandBuffer>> queries_in_flight; 52119fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 52129fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis bool skip = PreCallValidateGetQueryPoolResults(dev_data, queryPool, firstQuery, queryCount, flags, &queries_in_flight); 5213b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 5214cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 52159fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis VkResult result = 52169fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis dev_data->dispatch_table.GetQueryPoolResults(device, queryPool, firstQuery, queryCount, dataSize, pData, stride, flags); 52179fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis lock.lock(); 52189fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis PostCallRecordGetQueryPoolResults(dev_data, queryPool, firstQuery, queryCount, &queries_in_flight); 52199fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis lock.unlock(); 52209fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis return result; 52215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 52225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5223825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Return true if given ranges intersect, else false 5224825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Prereq : For both ranges, range->end - range->start > 0. This case should have already resulted 5225825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// in an error so not checking that here 5226825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// pad_ranges bool indicates a linear and non-linear comparison which requires padding 5227825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// In the case where padding is required, if an alias is encountered then a validation error is reported and skip_call 5228825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// may be set by the callback function so caller should merge in skip_call value if padding case is possible. 52297dc3fbb89e2dcf3df8fc2e6639a867a959fef3f3Tobin Ehlisstatic bool rangesIntersect(layer_data const *dev_data, MEMORY_RANGE const *range1, MEMORY_RANGE const *range2, bool *skip_call) { 52307dc3fbb89e2dcf3df8fc2e6639a867a959fef3f3Tobin Ehlis *skip_call = false; 5231825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis auto r1_start = range1->start; 5232825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis auto r1_end = range1->end; 5233825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis auto r2_start = range2->start; 5234825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis auto r2_end = range2->end; 5235825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis VkDeviceSize pad_align = 1; 5236825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis if (range1->linear != range2->linear) { 5237825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis pad_align = dev_data->phys_dev_properties.properties.limits.bufferImageGranularity; 5238825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis } 5239cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if ((r1_end & ~(pad_align - 1)) < (r2_start & ~(pad_align - 1))) return false; 5240cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if ((r1_start & ~(pad_align - 1)) > (r2_end & ~(pad_align - 1))) return false; 524147aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski 5242825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis if (range1->linear != range2->linear) { 524353ecec26e80e4d18b57d24ed6eb91a3c9da4b95cTobin Ehlis // In linear vs. non-linear case, warn of aliasing 5244825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis const char *r1_linear_str = range1->linear ? "Linear" : "Non-linear"; 5245825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis const char *r1_type_str = range1->image ? "image" : "buffer"; 5246825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis const char *r2_linear_str = range2->linear ? "linear" : "non-linear"; 5247825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis const char *r2_type_str = range2->image ? "image" : "buffer"; 5248825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis auto obj_type = range1->image ? VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT : VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT; 524953ecec26e80e4d18b57d24ed6eb91a3c9da4b95cTobin Ehlis *skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, obj_type, range1->handle, 0, 525053ecec26e80e4d18b57d24ed6eb91a3c9da4b95cTobin Ehlis MEMTRACK_INVALID_ALIASING, "MEM", "%s %s 0x%" PRIx64 " is aliased with %s %s 0x%" PRIx64 525153ecec26e80e4d18b57d24ed6eb91a3c9da4b95cTobin Ehlis " which may indicate a bug. For further info refer to the " 525253ecec26e80e4d18b57d24ed6eb91a3c9da4b95cTobin Ehlis "Buffer-Image Granularity section of the Vulkan specification. " 525353ecec26e80e4d18b57d24ed6eb91a3c9da4b95cTobin Ehlis "(https://www.khronos.org/registry/vulkan/specs/1.0-extensions/" 525453ecec26e80e4d18b57d24ed6eb91a3c9da4b95cTobin Ehlis "xhtml/vkspec.html#resources-bufferimagegranularity)", 525553ecec26e80e4d18b57d24ed6eb91a3c9da4b95cTobin Ehlis r1_linear_str, r1_type_str, range1->handle, r2_linear_str, r2_type_str, range2->handle); 525647aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski } 5257825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis // Ranges intersect 5258825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis return true; 525947aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski} 5260623548a271287ae55415e45e3c654ee66d4e79ffTobin Ehlis// Simplified rangesIntersect that calls above function to check range1 for intersection with offset & end addresses 5261c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinskibool rangesIntersect(layer_data const *dev_data, MEMORY_RANGE const *range1, VkDeviceSize offset, VkDeviceSize end) { 5262825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis // Create a local MEMORY_RANGE struct to wrap offset/size 5263825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis MEMORY_RANGE range_wrap; 5264825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis // Synch linear with range1 to avoid padding and potential validation error case 5265825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis range_wrap.linear = range1->linear; 5266825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis range_wrap.start = offset; 5267cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis range_wrap.end = end; 5268825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis bool tmp_bool; 52697dc3fbb89e2dcf3df8fc2e6639a867a959fef3f3Tobin Ehlis return rangesIntersect(dev_data, range1, &range_wrap, &tmp_bool); 5270825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis} 5271cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis// For given mem_info, set all ranges valid that intersect [offset-end] range 5272cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis// TODO : For ranges where there is no alias, we may want to create new buffer ranges that are valid 5273cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlisstatic void SetMemRangesValid(layer_data const *dev_data, DEVICE_MEM_INFO *mem_info, VkDeviceSize offset, VkDeviceSize end) { 5274cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis bool tmp_bool = false; 5275f6e16b28b808a342cb92768001afa2cfeee08a11Tobin Ehlis MEMORY_RANGE map_range = {}; 5276cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis map_range.linear = true; 5277cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis map_range.start = offset; 5278cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis map_range.end = end; 5279cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis for (auto &handle_range_pair : mem_info->bound_ranges) { 52807dc3fbb89e2dcf3df8fc2e6639a867a959fef3f3Tobin Ehlis if (rangesIntersect(dev_data, &handle_range_pair.second, &map_range, &tmp_bool)) { 5281cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis // TODO : WARN here if tmp_bool true? 5282cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis handle_range_pair.second.valid = true; 5283cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis } 5284cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis } 5285cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis} 5286825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Object with given handle is being bound to memory w/ given mem_info struct. 5287825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Track the newly bound memory range with given memoryOffset 5288825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Also scan any previous ranges, track aliased ranges with new range, and flag an error if a linear 5289825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// and non-linear range incorrectly overlap. 5290825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Return true if an error is flagged and the user callback returns "true", otherwise false 5291825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// is_image indicates an image object, otherwise handle is for a buffer 5292825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// is_linear indicates a buffer or linear image 52937992c34b28dd617787f0e4d34fd023f894495edbCort Stratton// api_name API entry point that triggered this call 5294825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlisstatic bool InsertMemoryRange(layer_data const *dev_data, uint64_t handle, DEVICE_MEM_INFO *mem_info, VkDeviceSize memoryOffset, 52957992c34b28dd617787f0e4d34fd023f894495edbCort Stratton VkMemoryRequirements memRequirements, bool is_image, bool is_linear, const char *api_name) { 5296825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis bool skip_call = false; 52975360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis MEMORY_RANGE range; 5298825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis 52997992c34b28dd617787f0e4d34fd023f894495edbCort Stratton if (memoryOffset >= mem_info->alloc_info.allocationSize) { 53007992c34b28dd617787f0e4d34fd023f894495edbCort Stratton UNIQUE_VALIDATION_ERROR_CODE error_code = is_image ? VALIDATION_ERROR_00805 : VALIDATION_ERROR_00793; 53017992c34b28dd617787f0e4d34fd023f894495edbCort Stratton skip_call = 53027992c34b28dd617787f0e4d34fd023f894495edbCort Stratton log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 53037992c34b28dd617787f0e4d34fd023f894495edbCort Stratton reinterpret_cast<uint64_t &>(mem_info->mem), __LINE__, error_code, "MEM", 53047992c34b28dd617787f0e4d34fd023f894495edbCort Stratton "In %s, attempting to bind memory (0x%" PRIxLEAST64 ") to object (0x%" PRIxLEAST64 53057992c34b28dd617787f0e4d34fd023f894495edbCort Stratton "), memoryOffset=0x%" PRIxLEAST64 " must be less than the memory allocation size 0x%" PRIxLEAST64 ". %s", 53067992c34b28dd617787f0e4d34fd023f894495edbCort Stratton api_name, reinterpret_cast<uint64_t &>(mem_info->mem), handle, memoryOffset, 53077992c34b28dd617787f0e4d34fd023f894495edbCort Stratton mem_info->alloc_info.allocationSize, validation_error_map[error_code]); 53087992c34b28dd617787f0e4d34fd023f894495edbCort Stratton } 53097992c34b28dd617787f0e4d34fd023f894495edbCort Stratton 5310825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis range.image = is_image; 531147aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski range.handle = handle; 5312825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis range.linear = is_linear; 5313f541bf53dee6daf82a4c8304354eac599a884d29Tobin Ehlis range.valid = mem_info->global_valid; 5314825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis range.memory = mem_info->mem; 531547aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski range.start = memoryOffset; 5316825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis range.size = memRequirements.size; 531747aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski range.end = memoryOffset + memRequirements.size - 1; 53185360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis range.aliases.clear(); 53195360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis // Update Memory aliasing 532075f4c8cec0996021a4258b9bf920a9e0fea4eac1Tobin 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 53215360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis // inserted into map before loop to get the final ptr, then we may enter loop when not needed & we check range against itself 53225360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis std::unordered_set<MEMORY_RANGE *> tmp_alias_ranges; 5323825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis for (auto &obj_range_pair : mem_info->bound_ranges) { 5324825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis auto check_range = &obj_range_pair.second; 53255360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis bool intersection_error = false; 53267dc3fbb89e2dcf3df8fc2e6639a867a959fef3f3Tobin Ehlis if (rangesIntersect(dev_data, &range, check_range, &intersection_error)) { 5327825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis skip_call |= intersection_error; 5328825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis range.aliases.insert(check_range); 53295360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis tmp_alias_ranges.insert(check_range); 5330825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis } 5331825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis } 53325360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis mem_info->bound_ranges[handle] = std::move(range); 53335360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis for (auto tmp_range : tmp_alias_ranges) { 53345360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis tmp_range->aliases.insert(&mem_info->bound_ranges[handle]); 53355360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis } 5336825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis if (is_image) 5337825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis mem_info->bound_images.insert(handle); 5338825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis else 5339825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis mem_info->bound_buffers.insert(handle); 5340825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis 5341825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis return skip_call; 534247aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski} 534347aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski 53449f12a235bb9c014878a98ce385b68587add2538aTobin Ehlisstatic bool InsertImageMemoryRange(layer_data const *dev_data, VkImage image, DEVICE_MEM_INFO *mem_info, VkDeviceSize mem_offset, 53457992c34b28dd617787f0e4d34fd023f894495edbCort Stratton VkMemoryRequirements mem_reqs, bool is_linear, const char *api_name) { 53467992c34b28dd617787f0e4d34fd023f894495edbCort Stratton return InsertMemoryRange(dev_data, reinterpret_cast<uint64_t &>(image), mem_info, mem_offset, mem_reqs, true, is_linear, 53477992c34b28dd617787f0e4d34fd023f894495edbCort Stratton api_name); 5348825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis} 5349825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis 53509f12a235bb9c014878a98ce385b68587add2538aTobin Ehlisstatic bool InsertBufferMemoryRange(layer_data const *dev_data, VkBuffer buffer, DEVICE_MEM_INFO *mem_info, VkDeviceSize mem_offset, 53517992c34b28dd617787f0e4d34fd023f894495edbCort Stratton VkMemoryRequirements mem_reqs, const char *api_name) { 53527992c34b28dd617787f0e4d34fd023f894495edbCort Stratton return InsertMemoryRange(dev_data, reinterpret_cast<uint64_t &>(buffer), mem_info, mem_offset, mem_reqs, false, true, api_name); 5353825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis} 5354825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis 5355825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Remove MEMORY_RANGE struct for give handle from bound_ranges of mem_info 5356825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// is_image indicates if handle is for image or buffer 5357825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// This function will also remove the handle-to-index mapping from the appropriate 5358825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// map and clean up any aliases for range being removed. 5359825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlisstatic void RemoveMemoryRange(uint64_t handle, DEVICE_MEM_INFO *mem_info, bool is_image) { 5360825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis auto erase_range = &mem_info->bound_ranges[handle]; 5361825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis for (auto alias_range : erase_range->aliases) { 5362825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis alias_range->aliases.erase(erase_range); 536347aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski } 53645360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis erase_range->aliases.clear(); 5365825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis mem_info->bound_ranges.erase(handle); 53661cba4e1b5940c6818572e05dcad5a3a47fafbc9eTobin Ehlis if (is_image) { 5367825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis mem_info->bound_images.erase(handle); 53681cba4e1b5940c6818572e05dcad5a3a47fafbc9eTobin Ehlis } else { 5369825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis mem_info->bound_buffers.erase(handle); 53701cba4e1b5940c6818572e05dcad5a3a47fafbc9eTobin Ehlis } 537147aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski} 537247aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski 5373842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinskivoid RemoveBufferMemoryRange(uint64_t handle, DEVICE_MEM_INFO *mem_info) { RemoveMemoryRange(handle, mem_info, false); } 5374825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis 53758c59133586421be878d393799b30044497f77727Mark Lobodzinskivoid RemoveImageMemoryRange(uint64_t handle, DEVICE_MEM_INFO *mem_info) { RemoveMemoryRange(handle, mem_info, true); } 5376825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis 5377bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyBuffer(VkDevice device, VkBuffer buffer, const VkAllocationCallbacks *pAllocator) { 537856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 5379e1056daefb39e3a3fed0088874725c56a1359e54Tobin Ehlis BUFFER_STATE *buffer_state = nullptr; 5380e1056daefb39e3a3fed0088874725c56a1359e54Tobin Ehlis VK_OBJECT obj_struct; 5381b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 5382e1056daefb39e3a3fed0088874725c56a1359e54Tobin Ehlis bool skip = PreCallValidateDestroyBuffer(dev_data, buffer, &buffer_state, &obj_struct); 5383e1056daefb39e3a3fed0088874725c56a1359e54Tobin Ehlis if (!skip) { 5384b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 53854a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyBuffer(device, buffer, pAllocator); 5386e1056daefb39e3a3fed0088874725c56a1359e54Tobin Ehlis lock.lock(); 5387405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (buffer != VK_NULL_HANDLE) { 5388405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyBuffer(dev_data, buffer, buffer_state, obj_struct); 5389405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 539047aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski } 53915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 53925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5393bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyBufferView(VkDevice device, VkBufferView bufferView, const VkAllocationCallbacks *pAllocator) { 539456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 5395f61017735c3291a2665487f2bac310578fc60a68Tobin Ehlis // Common data objects used pre & post call 53968e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis BUFFER_VIEW_STATE *buffer_view_state = nullptr; 53978e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis VK_OBJECT obj_struct; 5398a123662876eebfa844faa65ae3f071d3d77618ebTobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 53998e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis // Validate state before calling down chain, update common data if we'll be calling down chain 54008e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis bool skip = PreCallValidateDestroyBufferView(dev_data, bufferView, &buffer_view_state, &obj_struct); 540138e26abbaa884eb48bfec4ddb4e0ae2c90634e06Tobin Ehlis if (!skip) { 540238e26abbaa884eb48bfec4ddb4e0ae2c90634e06Tobin Ehlis lock.unlock(); 54034a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyBufferView(device, bufferView, pAllocator); 54048e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis lock.lock(); 5405405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (bufferView != VK_NULL_HANDLE) { 5406405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyBufferView(dev_data, bufferView, buffer_view_state, obj_struct); 5407405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 54085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 54095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 54105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 54112a0dd15a44bf665c97a3ff6adcbe7fe5853cdf60Tobin EhlisVKAPI_ATTR void VKAPI_CALL DestroyImage(VkDevice device, VkImage image, const VkAllocationCallbacks *pAllocator) { 541256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 54131facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis IMAGE_STATE *image_state = nullptr; 54142a0dd15a44bf665c97a3ff6adcbe7fe5853cdf60Tobin Ehlis VK_OBJECT obj_struct; 54152a0dd15a44bf665c97a3ff6adcbe7fe5853cdf60Tobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 54162a0dd15a44bf665c97a3ff6adcbe7fe5853cdf60Tobin Ehlis bool skip = PreCallValidateDestroyImage(dev_data, image, &image_state, &obj_struct); 54172a0dd15a44bf665c97a3ff6adcbe7fe5853cdf60Tobin Ehlis if (!skip) { 5418f940225c9e5e3e14b3f5a32d3ea360b585614600Tobin Ehlis lock.unlock(); 54194a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyImage(device, image, pAllocator); 54202a0dd15a44bf665c97a3ff6adcbe7fe5853cdf60Tobin Ehlis lock.lock(); 5421405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (image != VK_NULL_HANDLE) { 5422405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyImage(dev_data, image, image_state, obj_struct); 5423405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 54245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 54255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 54265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 54274261f1e2c91c90ce040ab36a13c9d92f6e988f10Mark Lobodzinskistatic bool ValidateMemoryTypes(const layer_data *dev_data, const DEVICE_MEM_INFO *mem_info, const uint32_t memory_type_bits, 5428f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen const char *funcName, UNIQUE_VALIDATION_ERROR_CODE msgCode) { 54294261f1e2c91c90ce040ab36a13c9d92f6e988f10Mark Lobodzinski bool skip_call = false; 5430de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis if (((1 << mem_info->alloc_info.memoryTypeIndex) & memory_type_bits) == 0) { 5431f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen skip_call = 5432f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 5433f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen reinterpret_cast<const uint64_t &>(mem_info->mem), __LINE__, msgCode, "MT", 5434f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen "%s(): MemoryRequirements->memoryTypeBits (0x%X) for this object type are not compatible with the memory " 5435f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen "type (0x%X) of this memory object 0x%" PRIx64 ". %s", 5436f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen funcName, memory_type_bits, mem_info->alloc_info.memoryTypeIndex, 5437f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen reinterpret_cast<const uint64_t &>(mem_info->mem), validation_error_map[msgCode]); 54384261f1e2c91c90ce040ab36a13c9d92f6e988f10Mark Lobodzinski } 54394261f1e2c91c90ce040ab36a13c9d92f6e988f10Mark Lobodzinski return skip_call; 54404261f1e2c91c90ce040ab36a13c9d92f6e988f10Mark Lobodzinski} 54414261f1e2c91c90ce040ab36a13c9d92f6e988f10Mark Lobodzinski 5442bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL BindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory mem, VkDeviceSize memoryOffset) { 544356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 54445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 5445b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 54465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Track objects tied to memory 54479f12a235bb9c014878a98ce385b68587add2538aTobin Ehlis uint64_t buffer_handle = reinterpret_cast<uint64_t &>(buffer); 5448888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis bool skip_call = SetMemBinding(dev_data, mem, buffer_handle, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, "vkBindBufferMemory"); 54499a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto buffer_state = GetBufferState(dev_data, buffer); 54505cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis if (buffer_state) { 54512eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis if (!buffer_state->memory_requirements_checked) { 54522eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis // There's not an explicit requirement in the spec to call vkGetBufferMemoryRequirements() prior to calling 54532eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis // BindBufferMemory but it's implied in that memory being bound must conform with VkMemoryRequirements from 54542eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis // vkGetBufferMemoryRequirements() 54552eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, 54562eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis buffer_handle, __LINE__, DRAWSTATE_INVALID_BUFFER, "DS", 54572eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis "vkBindBufferMemory(): Binding memory to buffer 0x%" PRIxLEAST64 54582eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis " but vkGetBufferMemoryRequirements() has not been called on that buffer.", 54592eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis buffer_handle); 54602eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis // Make the call for them so we can verify the state 54612eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis lock.unlock(); 54622eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis dev_data->dispatch_table.GetBufferMemoryRequirements(device, buffer, &buffer_state->requirements); 54632eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis lock.lock(); 54642eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis } 54655cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis buffer_state->binding.mem = mem; 54665cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis buffer_state->binding.offset = memoryOffset; 54672eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis buffer_state->binding.size = buffer_state->requirements.size; 546847aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski 546947aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski // Track and validate bound memory range information 54709a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto mem_info = GetMemObjInfo(dev_data, mem); 547157fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis if (mem_info) { 54727992c34b28dd617787f0e4d34fd023f894495edbCort Stratton skip_call |= 54737992c34b28dd617787f0e4d34fd023f894495edbCort Stratton InsertBufferMemoryRange(dev_data, buffer, mem_info, memoryOffset, buffer_state->requirements, "vkBindBufferMemory"); 54747992c34b28dd617787f0e4d34fd023f894495edbCort Stratton skip_call |= ValidateMemoryTypes(dev_data, mem_info, buffer_state->requirements.memoryTypeBits, "vkBindBufferMemory", 5475f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen VALIDATION_ERROR_00797); 547647aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski } 547747aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski 54782c905c8b5aca814df6c680348145ca48885f9f69Dustin Graves // Validate memory requirements alignment 54792eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis if (vk_safe_modulo(memoryOffset, buffer_state->requirements.alignment) != 0) { 5480f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 5481f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, VALIDATION_ERROR_02174, "DS", 5482cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkBindBufferMemory(): memoryOffset is 0x%" PRIxLEAST64 5483cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " but must be an integer multiple of the " 5484f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen "VkMemoryRequirements::alignment value 0x%" PRIxLEAST64 5485f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen ", returned from a call to vkGetBufferMemoryRequirements with buffer. %s", 5486f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen memoryOffset, buffer_state->requirements.alignment, validation_error_map[VALIDATION_ERROR_02174]); 54872c905c8b5aca814df6c680348145ca48885f9f69Dustin Graves } 5488ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller 54892c905c8b5aca814df6c680348145ca48885f9f69Dustin Graves // Validate device limits alignments 5490ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller static const VkBufferUsageFlagBits usage_list[3] = { 5491ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller static_cast<VkBufferUsageFlagBits>(VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT), 5492bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT}; 5493bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski static const char *memory_type[3] = {"texel", "uniform", "storage"}; 5494bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski static const char *offset_name[3] = {"minTexelBufferOffsetAlignment", "minUniformBufferOffsetAlignment", 5495bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "minStorageBufferOffsetAlignment"}; 5496cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski 5497cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // TODO: vk_validation_stats.py cannot abide braces immediately preceeding or following a validation error enum 5498cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // clang-format off 5499cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski static const UNIQUE_VALIDATION_ERROR_CODE msgCode[3] = { VALIDATION_ERROR_00794, VALIDATION_ERROR_00795, 5500cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VALIDATION_ERROR_00796 }; 5501cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // clang-format on 5502ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller 5503ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller // Keep this one fresh! 5504ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller const VkDeviceSize offset_requirement[3] = { 5505ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller dev_data->phys_dev_properties.properties.limits.minTexelBufferOffsetAlignment, 5506ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller dev_data->phys_dev_properties.properties.limits.minUniformBufferOffsetAlignment, 5507bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski dev_data->phys_dev_properties.properties.limits.minStorageBufferOffsetAlignment}; 55088718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis VkBufferUsageFlags usage = dev_data->bufferMap[buffer].get()->createInfo.usage; 5509ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller 5510ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller for (int i = 0; i < 3; i++) { 5511ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller if (usage & usage_list[i]) { 5512ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller if (vk_safe_modulo(memoryOffset, offset_requirement[i]) != 0) { 5513cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski skip_call |= log_msg( 5514cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, 5515cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, msgCode[i], "DS", "vkBindBufferMemory(): %s memoryOffset is 0x%" PRIxLEAST64 5516cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " but must be a multiple of " 5517cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "device limit %s 0x%" PRIxLEAST64 ". %s", 5518cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski memory_type[i], memoryOffset, offset_name[i], offset_requirement[i], validation_error_map[msgCode[i]]); 5519ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller } 55202c905c8b5aca814df6c680348145ca48885f9f69Dustin Graves } 55212c905c8b5aca814df6c680348145ca48885f9f69Dustin Graves } 55225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5523b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 552483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis if (!skip_call) { 55254a0754042cf090e131e9e769d8a3633c228625beChris Forbes result = dev_data->dispatch_table.BindBufferMemory(device, buffer, mem, memoryOffset); 55265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 55275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 55285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 55295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5530bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL GetBufferMemoryRequirements(VkDevice device, VkBuffer buffer, 5531bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkMemoryRequirements *pMemoryRequirements) { 553256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 553315caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis dev_data->dispatch_table.GetBufferMemoryRequirements(device, buffer, pMemoryRequirements); 55349a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto buffer_state = GetBufferState(dev_data, buffer); 553515caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis if (buffer_state) { 553615caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis buffer_state->requirements = *pMemoryRequirements; 55372eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis buffer_state->memory_requirements_checked = true; 553815caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis } 55395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 55405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5541bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL GetImageMemoryRequirements(VkDevice device, VkImage image, VkMemoryRequirements *pMemoryRequirements) { 554256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 554315caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis dev_data->dispatch_table.GetImageMemoryRequirements(device, image, pMemoryRequirements); 55449a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_state = GetImageState(dev_data, image); 554515caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis if (image_state) { 554615caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis image_state->requirements = *pMemoryRequirements; 55472eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis image_state->memory_requirements_checked = true; 554815caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis } 55495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 5550593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 5551bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyImageView(VkDevice device, VkImageView imageView, const VkAllocationCallbacks *pAllocator) { 555256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 5553f61017735c3291a2665487f2bac310578fc60a68Tobin Ehlis // Common data objects used pre & post call 5554f61017735c3291a2665487f2bac310578fc60a68Tobin Ehlis IMAGE_VIEW_STATE *image_view_state = nullptr; 5555f61017735c3291a2665487f2bac310578fc60a68Tobin Ehlis VK_OBJECT obj_struct; 5556a123662876eebfa844faa65ae3f071d3d77618ebTobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 5557f61017735c3291a2665487f2bac310578fc60a68Tobin Ehlis bool skip = PreCallValidateDestroyImageView(dev_data, imageView, &image_view_state, &obj_struct); 5558d85c42a6c1d6ad7a6f684c5bd793aab482b7705cTobin Ehlis if (!skip) { 5559d85c42a6c1d6ad7a6f684c5bd793aab482b7705cTobin Ehlis lock.unlock(); 55604a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyImageView(device, imageView, pAllocator); 5561f61017735c3291a2665487f2bac310578fc60a68Tobin Ehlis lock.lock(); 5562405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (imageView != VK_NULL_HANDLE) { 5563405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyImageView(dev_data, imageView, image_view_state, obj_struct); 5564405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 5565d85c42a6c1d6ad7a6f684c5bd793aab482b7705cTobin Ehlis } 55665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 55675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5568bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyShaderModule(VkDevice device, VkShaderModule shaderModule, 5569bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator) { 557056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 5571918c283ac4f8c604b79abd0c8b5706d2a7352a34Chris Forbes 5572b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 557351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->shaderModuleMap.erase(shaderModule); 5574b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 5575918c283ac4f8c604b79abd0c8b5706d2a7352a34Chris Forbes 557651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->dispatch_table.DestroyShaderModule(device, shaderModule, pAllocator); 55775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 55785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 55794c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlisstatic bool PreCallValidateDestroyPipeline(layer_data *dev_data, VkPipeline pipeline, PIPELINE_STATE **pipeline_state, 55808bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis VK_OBJECT *obj_struct) { 558194165f5005d1fa37801d49067fe7751789b89d27Tobin Ehlis *pipeline_state = getPipelineState(dev_data, pipeline); 558294165f5005d1fa37801d49067fe7751789b89d27Tobin Ehlis *obj_struct = {reinterpret_cast<uint64_t &>(pipeline), VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT}; 5583cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_pipeline) return false; 55848bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis bool skip = false; 55858bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis if (*pipeline_state) { 55861803032f91d772ff3589c9f5a51ade5b299ba538Tobin Ehlis skip |= ValidateObjectNotInUse(dev_data, *pipeline_state, *obj_struct, VALIDATION_ERROR_00555); 55878bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis } 55888bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis return skip; 55898bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis} 55908bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis 55914c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlisstatic void PostCallRecordDestroyPipeline(layer_data *dev_data, VkPipeline pipeline, PIPELINE_STATE *pipeline_state, 55928bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis VK_OBJECT obj_struct) { 55938bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis // Any bound cmd buffers are now invalid 559439c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis invalidateCommandBuffers(dev_data, pipeline_state->cb_bindings, obj_struct); 55958bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis dev_data->pipelineMap.erase(pipeline); 55968bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis} 55978bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis 5598bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyPipeline(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks *pAllocator) { 559956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 56004c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis PIPELINE_STATE *pipeline_state = nullptr; 56018bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis VK_OBJECT obj_struct; 5602e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 56038bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis bool skip = PreCallValidateDestroyPipeline(dev_data, pipeline, &pipeline_state, &obj_struct); 5604f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis if (!skip) { 5605f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis lock.unlock(); 56064a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyPipeline(device, pipeline, pAllocator); 56078bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis lock.lock(); 5608405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (pipeline != VK_NULL_HANDLE) { 5609405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyPipeline(dev_data, pipeline, pipeline_state, obj_struct); 5610405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 5611f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis } 56125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 56135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5614bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyPipelineLayout(VkDevice device, VkPipelineLayout pipelineLayout, 5615bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator) { 561656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 5617e28cddb35c63274c13873b9a7060ad43b255c6f1Tobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 56186792ea7cc0ce5fa64b7bd6c946460608cbda91c7Tobin Ehlis dev_data->pipelineLayoutMap.erase(pipelineLayout); 5619e28cddb35c63274c13873b9a7060ad43b255c6f1Tobin Ehlis lock.unlock(); 5620e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis 56214a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyPipelineLayout(device, pipelineLayout, pAllocator); 56225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 56235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5624d31a44af6da568692a73201825459689c9431867Tobin Ehlisstatic bool PreCallValidateDestroySampler(layer_data *dev_data, VkSampler sampler, SAMPLER_STATE **sampler_state, 5625806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis VK_OBJECT *obj_struct) { 56269a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *sampler_state = GetSamplerState(dev_data, sampler); 562794165f5005d1fa37801d49067fe7751789b89d27Tobin Ehlis *obj_struct = {reinterpret_cast<uint64_t &>(sampler), VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT}; 5628cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_sampler) return false; 5629806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis bool skip = false; 5630806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis if (*sampler_state) { 5631806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis skip |= ValidateObjectNotInUse(dev_data, *sampler_state, *obj_struct, VALIDATION_ERROR_00837); 5632806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis } 5633806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis return skip; 5634806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis} 5635806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis 5636d31a44af6da568692a73201825459689c9431867Tobin Ehlisstatic void PostCallRecordDestroySampler(layer_data *dev_data, VkSampler sampler, SAMPLER_STATE *sampler_state, 5637806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis VK_OBJECT obj_struct) { 5638806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis // Any bound cmd buffers are now invalid 5639cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (sampler_state) invalidateCommandBuffers(dev_data, sampler_state->cb_bindings, obj_struct); 5640806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis dev_data->samplerMap.erase(sampler); 5641806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis} 5642806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis 5643bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroySampler(VkDevice device, VkSampler sampler, const VkAllocationCallbacks *pAllocator) { 564456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 5645d31a44af6da568692a73201825459689c9431867Tobin Ehlis SAMPLER_STATE *sampler_state = nullptr; 5646806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis VK_OBJECT obj_struct; 564756f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 5648806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis bool skip = PreCallValidateDestroySampler(dev_data, sampler, &sampler_state, &obj_struct); 5649f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis if (!skip) { 5650f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis lock.unlock(); 56514a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroySampler(device, sampler, pAllocator); 5652806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis lock.lock(); 5653405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (sampler != VK_NULL_HANDLE) { 5654405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroySampler(dev_data, sampler, sampler_state, obj_struct); 5655405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 5656f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis } 56575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 56585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 565979c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlisstatic void PostCallRecordDestroyDescriptorSetLayout(layer_data *dev_data, VkDescriptorSetLayout ds_layout) { 566079c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlis dev_data->descriptorSetLayoutMap.erase(ds_layout); 566179c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlis} 566279c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlis 5663bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyDescriptorSetLayout(VkDevice device, VkDescriptorSetLayout descriptorSetLayout, 5664bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator) { 566556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 566679c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlis dev_data->dispatch_table.DestroyDescriptorSetLayout(device, descriptorSetLayout, pAllocator); 566779c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 566879c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlis PostCallRecordDestroyDescriptorSetLayout(dev_data, descriptorSetLayout); 56695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 56705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5671c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlisstatic bool PreCallValidateDestroyDescriptorPool(layer_data *dev_data, VkDescriptorPool pool, 5672a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis DESCRIPTOR_POOL_STATE **desc_pool_state, VK_OBJECT *obj_struct) { 56739a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *desc_pool_state = GetDescriptorPoolState(dev_data, pool); 567494165f5005d1fa37801d49067fe7751789b89d27Tobin Ehlis *obj_struct = {reinterpret_cast<uint64_t &>(pool), VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT}; 5675cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_descriptor_pool) return false; 5676c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis bool skip = false; 5677c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis if (*desc_pool_state) { 56781803032f91d772ff3589c9f5a51ade5b299ba538Tobin Ehlis skip |= ValidateObjectNotInUse(dev_data, *desc_pool_state, *obj_struct, VALIDATION_ERROR_00901); 5679c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis } 5680c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis return skip; 5681c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis} 5682c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis 5683c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlisstatic void PostCallRecordDestroyDescriptorPool(layer_data *dev_data, VkDescriptorPool descriptorPool, 5684a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis DESCRIPTOR_POOL_STATE *desc_pool_state, VK_OBJECT obj_struct) { 5685c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis // Any bound cmd buffers are now invalid 568639c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis invalidateCommandBuffers(dev_data, desc_pool_state->cb_bindings, obj_struct); 5687c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis // Free sets that were in this pool 5688c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis for (auto ds : desc_pool_state->sets) { 5689c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis freeDescriptorSet(dev_data, ds); 5690c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis } 5691c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis dev_data->descriptorPoolMap.erase(descriptorPool); 5692c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis} 5693c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis 5694bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, 5695bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator) { 569656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 5697a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis DESCRIPTOR_POOL_STATE *desc_pool_state = nullptr; 5698c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis VK_OBJECT obj_struct; 5699c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 5700c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis bool skip = PreCallValidateDestroyDescriptorPool(dev_data, descriptorPool, &desc_pool_state, &obj_struct); 5701c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis if (!skip) { 5702c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis lock.unlock(); 5703c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis dev_data->dispatch_table.DestroyDescriptorPool(device, descriptorPool, pAllocator); 5704c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis lock.lock(); 5705405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (descriptorPool != VK_NULL_HANDLE) { 5706405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyDescriptorPool(dev_data, descriptorPool, desc_pool_state, obj_struct); 5707405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 5708c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis } 57095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 5710bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis// Verify cmdBuffer in given cb_node is not in global in-flight set, and return skip_call result 5711bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis// If this is a secondary command buffer, then make sure its primary is also in-flight 5712bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis// If primary is not in-flight, then remove secondary from global in-flight set 5713bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis// This function is only valid at a point when cmdBuffer is being reset or freed 5714cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlisstatic bool checkCommandBufferInFlight(layer_data *dev_data, const GLOBAL_CB_NODE *cb_node, const char *action, 5715cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlis UNIQUE_VALIDATION_ERROR_CODE error_code) { 5716bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis bool skip_call = false; 5717bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis if (dev_data->globalInFlightCmdBuffers.count(cb_node->commandBuffer)) { 5718bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis // Primary CB or secondary where primary is also in-flight is an error 5719bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis if ((cb_node->createInfo.level != VK_COMMAND_BUFFER_LEVEL_SECONDARY) || 5720bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis (dev_data->globalInFlightCmdBuffers.count(cb_node->primaryCommandBuffer))) { 5721cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlis skip_call |= 5722cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 5723cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlis reinterpret_cast<const uint64_t &>(cb_node->commandBuffer), __LINE__, error_code, "DS", 5724226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "Attempt to %s command buffer (0x%p) which is in use. %s", action, cb_node->commandBuffer, 5725226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis validation_error_map[error_code]); 5726bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis } 5727bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis } 5728bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis return skip_call; 5729bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis} 5730a964cad279f9749cd9ebfc7555247ff3bff26d53Chris Forbes 5731bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis// Iterate over all cmdBuffers in given commandPool and verify that each is not in use 5732cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlisstatic bool checkCommandBuffersInFlight(layer_data *dev_data, COMMAND_POOL_NODE *pPool, const char *action, 5733cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlis UNIQUE_VALIDATION_ERROR_CODE error_code) { 5734bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis bool skip_call = false; 5735a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes for (auto cmd_buffer : pPool->commandBuffers) { 5736a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes if (dev_data->globalInFlightCmdBuffers.count(cmd_buffer)) { 57379a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis skip_call |= checkCommandBufferInFlight(dev_data, GetCBNode(dev_data, cmd_buffer), action, error_code); 5738bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis } 5739bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis } 5740bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis return skip_call; 5741bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis} 57425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5743a01b5eb150981aad061238e64b173d0da8c11140Chris Forbesstatic void clearCommandBuffersInFlight(layer_data *dev_data, COMMAND_POOL_NODE *pPool) { 5744a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes for (auto cmd_buffer : pPool->commandBuffers) { 5745a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes dev_data->globalInFlightCmdBuffers.erase(cmd_buffer); 5746a964cad279f9749cd9ebfc7555247ff3bff26d53Chris Forbes } 5747a964cad279f9749cd9ebfc7555247ff3bff26d53Chris Forbes} 5748a964cad279f9749cd9ebfc7555247ff3bff26d53Chris Forbes 5749bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL FreeCommandBuffers(VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount, 5750bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkCommandBuffer *pCommandBuffers) { 575156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 57525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool skip_call = false; 5753b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 5754c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes 57555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < commandBufferCount; i++) { 57569a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, pCommandBuffers[i]); 57575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Delete CB information structure, and remove from commandBufferMap 57589f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis if (cb_node) { 5759cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlis skip_call |= checkCommandBufferInFlight(dev_data, cb_node, "free", VALIDATION_ERROR_00096); 5760c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes } 5761c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes } 5762c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes 5763cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip_call) return; 5764c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes 57659a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pPool = GetCommandPoolNode(dev_data, commandPool); 5766c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes for (uint32_t i = 0; i < commandBufferCount; i++) { 57679a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, pCommandBuffers[i]); 5768c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes // Delete CB information structure, and remove from commandBufferMap 57699f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis if (cb_node) { 57709f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis dev_data->globalInFlightCmdBuffers.erase(cb_node->commandBuffer); 57715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // reset prior to delete for data clean-up 57729f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis resetCB(dev_data, cb_node->commandBuffer); 57739f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis dev_data->commandBufferMap.erase(cb_node->commandBuffer); 57749f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis delete cb_node; 57755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 57765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 57775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Remove commandBuffer reference from commandPoolMap 5778c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes pPool->commandBuffers.remove(pCommandBuffers[i]); 57795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5780b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 5781e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis 57824a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.FreeCommandBuffers(device, commandPool, commandBufferCount, pCommandBuffers); 57835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 57845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 578589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateCommandPool(VkDevice device, const VkCommandPoolCreateInfo *pCreateInfo, 5786bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkCommandPool *pCommandPool) { 578756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 57885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 57894a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateCommandPool(device, pCreateInfo, pAllocator, pCommandPool); 57905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 57915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 5792b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 57935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->commandPoolMap[*pCommandPool].createFlags = pCreateInfo->flags; 57945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->commandPoolMap[*pCommandPool].queueFamilyIndex = pCreateInfo->queueFamilyIndex; 57955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 57965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 57975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 57985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 579989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateQueryPool(VkDevice device, const VkQueryPoolCreateInfo *pCreateInfo, 580089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkQueryPool *pQueryPool) { 580156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 58020c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis bool skip = false; 58030c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis if (pCreateInfo && pCreateInfo->queryType == VK_QUERY_TYPE_PIPELINE_STATISTICS) { 58040c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis if (!dev_data->enabled_features.pipelineStatisticsQuery) { 58050c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, 58060c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis __LINE__, VALIDATION_ERROR_01006, "DS", 58070c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis "Query pool with type VK_QUERY_TYPE_PIPELINE_STATISTICS created on a device " 58080c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis "with VkDeviceCreateInfo.pEnabledFeatures.pipelineStatisticsQuery == VK_FALSE. %s", 58090c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis validation_error_map[VALIDATION_ERROR_01006]); 58100c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis } 58110c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis } 58120c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis 58130c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 58140c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis if (!skip) { 58150c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis result = dev_data->dispatch_table.CreateQueryPool(device, pCreateInfo, pAllocator, pQueryPool); 58160c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis } 58175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (result == VK_SUCCESS) { 5818b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 5819eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis QUERY_POOL_NODE *qp_node = &dev_data->queryPoolMap[*pQueryPool]; 5820eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis qp_node->createInfo = *pCreateInfo; 58215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 58225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 58235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 58245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 58255f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlisstatic bool PreCallValidateDestroyCommandPool(layer_data *dev_data, VkCommandPool pool, COMMAND_POOL_NODE **cp_state) { 58269a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *cp_state = GetCommandPoolNode(dev_data, pool); 5827cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_command_pool) return false; 58285f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis bool skip = false; 58295f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis if (*cp_state) { 58305f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis // Verify that command buffers in pool are complete (not in-flight) 58315f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis skip |= checkCommandBuffersInFlight(dev_data, *cp_state, "destroy command pool with", VALIDATION_ERROR_00077); 58325f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis } 58335f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis return skip; 58345f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis} 58355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 58365f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlisstatic void PostCallRecordDestroyCommandPool(layer_data *dev_data, VkCommandPool pool, COMMAND_POOL_NODE *cp_state) { 58379f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis // Must remove cmdpool from cmdpoolmap, after removing all cmdbuffers in its list from the commandBufferMap 58385f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis clearCommandBuffersInFlight(dev_data, cp_state); 58395f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis for (auto cb : cp_state->commandBuffers) { 5840a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes clear_cmd_buf_and_mem_references(dev_data, cb); 58419a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, cb); 5842d61de0e68063faa169a9a632f811c9c9adec9897Tobin Ehlis // Remove references to this cb_node prior to delete 5843d61de0e68063faa169a9a632f811c9c9adec9897Tobin Ehlis // TODO : Need better solution here, resetCB? 58447165385f3a39f1f951f3a6a9a06ed2cce4642b6dMark Lobodzinski for (auto obj : cb_node->object_bindings) { 58457165385f3a39f1f951f3a6a9a06ed2cce4642b6dMark Lobodzinski removeCommandBufferBinding(dev_data, &obj, cb_node); 58467165385f3a39f1f951f3a6a9a06ed2cce4642b6dMark Lobodzinski } 5847d61de0e68063faa169a9a632f811c9c9adec9897Tobin Ehlis for (auto framebuffer : cb_node->framebuffers) { 58489a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto fb_state = GetFramebufferState(dev_data, framebuffer); 5849cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (fb_state) fb_state->cb_bindings.erase(cb_node); 5850d61de0e68063faa169a9a632f811c9c9adec9897Tobin Ehlis } 5851cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski dev_data->commandBufferMap.erase(cb); // Remove this command buffer 5852cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski delete cb_node; // delete CB info structure 5853a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes } 58545f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis dev_data->commandPoolMap.erase(pool); 58555f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis} 5856e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis 58575f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis// Destroy commandPool along with all of the commandBuffers allocated from that pool 58585f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin EhlisVKAPI_ATTR void VKAPI_CALL DestroyCommandPool(VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks *pAllocator) { 585956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 58605f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis COMMAND_POOL_NODE *cp_state = nullptr; 58615f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 58625f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis bool skip = PreCallValidateDestroyCommandPool(dev_data, commandPool, &cp_state); 58635f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis if (!skip) { 58645f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis lock.unlock(); 58655f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis dev_data->dispatch_table.DestroyCommandPool(device, commandPool, pAllocator); 58665f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis lock.lock(); 5867405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (commandPool != VK_NULL_HANDLE) { 5868405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyCommandPool(dev_data, commandPool, cp_state); 5869405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 58705f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis } 58715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 58725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5873bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL ResetCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolResetFlags flags) { 587456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 587583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 5876400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis 58771ec6311a8537f4467db08eacbd762ebaa87e70b0Chris Forbes std::unique_lock<std::mutex> lock(global_lock); 58789a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pPool = GetCommandPoolNode(dev_data, commandPool); 5879cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlis skip_call |= checkCommandBuffersInFlight(dev_data, pPool, "reset command pool with", VALIDATION_ERROR_00072); 58801ec6311a8537f4467db08eacbd762ebaa87e70b0Chris Forbes lock.unlock(); 5881a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes 5882cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip_call) return VK_ERROR_VALIDATION_FAILED_EXT; 58835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 58844a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.ResetCommandPool(device, commandPool, flags); 58855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 58865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Reset all of the CBs allocated from this pool 58875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 58881ec6311a8537f4467db08eacbd762ebaa87e70b0Chris Forbes lock.lock(); 5889a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes clearCommandBuffersInFlight(dev_data, pPool); 5890a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes for (auto cmdBuffer : pPool->commandBuffers) { 5891a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes resetCB(dev_data, cmdBuffer); 58925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 58931ec6311a8537f4467db08eacbd762ebaa87e70b0Chris Forbes lock.unlock(); 58945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 58955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 58965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 58975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 589889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL ResetFences(VkDevice device, uint32_t fenceCount, const VkFence *pFences) { 589956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 590083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 5901b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 59025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < fenceCount; ++i) { 59039a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pFence = GetFenceNode(dev_data, pFences[i]); 5904090da73358f71ba026e2474a822fecf55267d166Chris Forbes if (pFence && pFence->state == FENCE_INFLIGHT) { 590583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, 59064527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton reinterpret_cast<const uint64_t &>(pFences[i]), __LINE__, VALIDATION_ERROR_00183, "DS", 59074527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton "Fence 0x%" PRIx64 " is in use. %s", reinterpret_cast<const uint64_t &>(pFences[i]), 59084527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton validation_error_map[VALIDATION_ERROR_00183]); 59095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 59105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5911b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 5912090da73358f71ba026e2474a822fecf55267d166Chris Forbes 5913cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip_call) return VK_ERROR_VALIDATION_FAILED_EXT; 5914090da73358f71ba026e2474a822fecf55267d166Chris Forbes 59154a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.ResetFences(device, fenceCount, pFences); 5916090da73358f71ba026e2474a822fecf55267d166Chris Forbes 5917090da73358f71ba026e2474a822fecf55267d166Chris Forbes if (result == VK_SUCCESS) { 5918090da73358f71ba026e2474a822fecf55267d166Chris Forbes lock.lock(); 5919090da73358f71ba026e2474a822fecf55267d166Chris Forbes for (uint32_t i = 0; i < fenceCount; ++i) { 59209a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pFence = GetFenceNode(dev_data, pFences[i]); 5921090da73358f71ba026e2474a822fecf55267d166Chris Forbes if (pFence) { 5922090da73358f71ba026e2474a822fecf55267d166Chris Forbes pFence->state = FENCE_UNSIGNALED; 5923090da73358f71ba026e2474a822fecf55267d166Chris Forbes } 5924090da73358f71ba026e2474a822fecf55267d166Chris Forbes } 5925090da73358f71ba026e2474a822fecf55267d166Chris Forbes lock.unlock(); 5926090da73358f71ba026e2474a822fecf55267d166Chris Forbes } 5927090da73358f71ba026e2474a822fecf55267d166Chris Forbes 59285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 59295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 59305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5931e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis// For given cb_nodes, invalidate them and track object causing invalidation 59320a4087f99558069e9f6a437ff2dbb5a9c1c22ccaTobin Ehlisvoid invalidateCommandBuffers(const layer_data *dev_data, std::unordered_set<GLOBAL_CB_NODE *> const &cb_nodes, VK_OBJECT obj) { 5933e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis for (auto cb_node : cb_nodes) { 593439c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis if (cb_node->state == CB_RECORDING) { 593539c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 5936fefa20333f94ea75877cca53d0631542cd9d0432Tobin Ehlis (uint64_t)(cb_node->commandBuffer), __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER, "DS", 5937226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "Invalidating a command buffer that's currently being recorded: 0x%p.", cb_node->commandBuffer); 593839c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis } 5939e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis cb_node->state = CB_INVALID; 5940e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis cb_node->broken_bindings.push_back(obj); 5941e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis } 5942e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis} 5943e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis 5944c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlisstatic bool PreCallValidateDestroyFramebuffer(layer_data *dev_data, VkFramebuffer framebuffer, 5945c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis FRAMEBUFFER_STATE **framebuffer_state, VK_OBJECT *obj_struct) { 59469a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *framebuffer_state = GetFramebufferState(dev_data, framebuffer); 594794165f5005d1fa37801d49067fe7751789b89d27Tobin Ehlis *obj_struct = {reinterpret_cast<uint64_t &>(framebuffer), VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT}; 5948cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_framebuffer) return false; 5949728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis bool skip = false; 5950728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis if (*framebuffer_state) { 5951728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis skip |= ValidateObjectNotInUse(dev_data, *framebuffer_state, *obj_struct, VALIDATION_ERROR_00422); 5952728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis } 5953728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis return skip; 5954728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis} 5955728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis 5956c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlisstatic void PostCallRecordDestroyFramebuffer(layer_data *dev_data, VkFramebuffer framebuffer, FRAMEBUFFER_STATE *framebuffer_state, 5957728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis VK_OBJECT obj_struct) { 595839c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis invalidateCommandBuffers(dev_data, framebuffer_state->cb_bindings, obj_struct); 5959728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis dev_data->frameBufferMap.erase(framebuffer); 5960728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis} 5961728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis 5962bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyFramebuffer(VkDevice device, VkFramebuffer framebuffer, const VkAllocationCallbacks *pAllocator) { 596356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 5964c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis FRAMEBUFFER_STATE *framebuffer_state = nullptr; 5965728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis VK_OBJECT obj_struct; 5966b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 5967728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis bool skip = PreCallValidateDestroyFramebuffer(dev_data, framebuffer, &framebuffer_state, &obj_struct); 5968728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis if (!skip) { 5969728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis lock.unlock(); 5970728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis dev_data->dispatch_table.DestroyFramebuffer(device, framebuffer, pAllocator); 5971728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis lock.lock(); 5972405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (framebuffer != VK_NULL_HANDLE) { 5973405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyFramebuffer(dev_data, framebuffer, framebuffer_state, obj_struct); 5974405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 59755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 59765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 59775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 59780ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlisstatic bool PreCallValidateDestroyRenderPass(layer_data *dev_data, VkRenderPass render_pass, RENDER_PASS_STATE **rp_state, 59790ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis VK_OBJECT *obj_struct) { 59809a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *rp_state = GetRenderPassState(dev_data, render_pass); 598194165f5005d1fa37801d49067fe7751789b89d27Tobin Ehlis *obj_struct = {reinterpret_cast<uint64_t &>(render_pass), VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT}; 5982cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_renderpass) return false; 59830ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis bool skip = false; 59840ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis if (*rp_state) { 59850ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis skip |= ValidateObjectNotInUse(dev_data, *rp_state, *obj_struct, VALIDATION_ERROR_00393); 59860ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis } 59870ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis return skip; 59880ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis} 59890ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis 59900ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlisstatic void PostCallRecordDestroyRenderPass(layer_data *dev_data, VkRenderPass render_pass, RENDER_PASS_STATE *rp_state, 59910ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis VK_OBJECT obj_struct) { 599239c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis invalidateCommandBuffers(dev_data, rp_state->cb_bindings, obj_struct); 59930ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis dev_data->renderPassMap.erase(render_pass); 59940ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis} 59950ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis 5996bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyRenderPass(VkDevice device, VkRenderPass renderPass, const VkAllocationCallbacks *pAllocator) { 599756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 59980ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis RENDER_PASS_STATE *rp_state = nullptr; 59990ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis VK_OBJECT obj_struct; 6000e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 60010ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis bool skip = PreCallValidateDestroyRenderPass(dev_data, renderPass, &rp_state, &obj_struct); 6002a9fbfe0c622e9fa4b56ddd015ed4c3c409020c2eTobin Ehlis if (!skip) { 6003a9fbfe0c622e9fa4b56ddd015ed4c3c409020c2eTobin Ehlis lock.unlock(); 60044a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyRenderPass(device, renderPass, pAllocator); 60050ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis lock.lock(); 6006405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (renderPass != VK_NULL_HANDLE) { 6007405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyRenderPass(dev_data, renderPass, rp_state, obj_struct); 6008405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 6009a9fbfe0c622e9fa4b56ddd015ed4c3c409020c2eTobin Ehlis } 60105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 60115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 601289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateBuffer(VkDevice device, const VkBufferCreateInfo *pCreateInfo, 601389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkBuffer *pBuffer) { 601456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 60153683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski std::unique_lock<std::mutex> lock(global_lock); 60163683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski bool skip = PreCallValidateCreateBuffer(dev_data, pCreateInfo); 60173683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski lock.unlock(); 60183683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski 60193683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 60204a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateBuffer(device, pCreateInfo, pAllocator, pBuffer); 60215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 60225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 60233683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski lock.lock(); 60243683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski PostCallRecordCreateBuffer(dev_data, pCreateInfo, pBuffer); 60253683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski lock.unlock(); 60265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 60275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 60285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 60295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 603089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateBufferView(VkDevice device, const VkBufferViewCreateInfo *pCreateInfo, 603189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkBufferView *pView) { 603256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 60338c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young std::unique_lock<std::mutex> lock(global_lock); 60348c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young bool skip_call = PreCallValidateCreateBufferView(dev_data, pCreateInfo); 60358c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young lock.unlock(); 6036cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip_call) return VK_ERROR_VALIDATION_FAILED_EXT; 60374a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateBufferView(device, pCreateInfo, pAllocator, pView); 60385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 60398c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young lock.lock(); 60403683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski PostCallRecordCreateBufferView(dev_data, pCreateInfo, pView); 60418c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young lock.unlock(); 60425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 60435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 60445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 60455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 60468dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski// Access helper functions for external modules 6047d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinskiconst VkFormatProperties *GetFormatProperties(core_validation::layer_data *device_data, VkFormat format) { 6048d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski VkFormatProperties *format_properties = new VkFormatProperties; 6049d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski instance_layer_data *instance_data = 6050d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski GetLayerDataPtr(get_dispatch_key(device_data->instance_data->instance), instance_layer_data_map); 6051d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski instance_data->dispatch_table.GetPhysicalDeviceFormatProperties(device_data->physical_device, format, format_properties); 6052d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski return format_properties; 60538dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski} 60548dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski 6055d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinskiconst VkImageFormatProperties *GetImageFormatProperties(core_validation::layer_data *device_data, VkFormat format, 6056d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski VkImageType image_type, VkImageTiling tiling, VkImageUsageFlags usage, 6057d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski VkImageCreateFlags flags) { 6058d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski VkImageFormatProperties *image_format_properties = new VkImageFormatProperties; 6059d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski instance_layer_data *instance_data = 6060d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski GetLayerDataPtr(get_dispatch_key(device_data->instance_data->instance), instance_layer_data_map); 6061d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski instance_data->dispatch_table.GetPhysicalDeviceImageFormatProperties(device_data->physical_device, format, image_type, tiling, 6062d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski usage, flags, image_format_properties); 6063d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski return image_format_properties; 60648dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski} 60658dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski 60668dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinskiconst debug_report_data *GetReportData(core_validation::layer_data *device_data) { return device_data->report_data; } 60678dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski 60688dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinskiconst VkPhysicalDeviceProperties *GetPhysicalDeviceProperties(core_validation::layer_data *device_data) { 60698dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski return &device_data->phys_dev_props; 60708dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski} 60718dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski 60728c59133586421be878d393799b30044497f77727Mark Lobodzinskiconst CHECK_DISABLED *GetDisables(core_validation::layer_data *device_data) { return &device_data->instance_data->disabled; } 60738c59133586421be878d393799b30044497f77727Mark Lobodzinski 60748c59133586421be878d393799b30044497f77727Mark Lobodzinskistd::unordered_map<VkImage, std::unique_ptr<IMAGE_STATE>> *GetImageMap(core_validation::layer_data *device_data) { 60758c59133586421be878d393799b30044497f77727Mark Lobodzinski return &device_data->imageMap; 60768c59133586421be878d393799b30044497f77727Mark Lobodzinski} 60778c59133586421be878d393799b30044497f77727Mark Lobodzinski 60788c59133586421be878d393799b30044497f77727Mark Lobodzinskistd::unordered_map<VkImage, std::vector<ImageSubresourcePair>> *GetImageSubresourceMap(core_validation::layer_data *device_data) { 60798c59133586421be878d393799b30044497f77727Mark Lobodzinski return &device_data->imageSubresourceMap; 60808c59133586421be878d393799b30044497f77727Mark Lobodzinski} 60818c59133586421be878d393799b30044497f77727Mark Lobodzinski 60828c59133586421be878d393799b30044497f77727Mark Lobodzinskistd::unordered_map<ImageSubresourcePair, IMAGE_LAYOUT_NODE> *GetImageLayoutMap(layer_data *device_data) { 60838c59133586421be878d393799b30044497f77727Mark Lobodzinski return &device_data->imageLayoutMap; 60848c59133586421be878d393799b30044497f77727Mark Lobodzinski} 60858c59133586421be878d393799b30044497f77727Mark Lobodzinski 60863683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinskistd::unordered_map<VkBuffer, std::unique_ptr<BUFFER_STATE>> *GetBufferMap(layer_data *device_data) { 60873683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski return &device_data->bufferMap; 60883683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski} 60893683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski 60903683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinskistd::unordered_map<VkBufferView, std::unique_ptr<BUFFER_VIEW_STATE>> *GetBufferViewMap(layer_data *device_data) { 60913683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski return &device_data->bufferViewMap; 60923683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski} 60933683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski 60941c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinskistd::unordered_map<VkImageView, std::unique_ptr<IMAGE_VIEW_STATE>> *GetImageViewMap(layer_data *device_data) { 60951c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski return &device_data->imageViewMap; 60961c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski} 60971c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski 6098d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinskiconst PHYS_DEV_PROPERTIES_NODE *GetPhysDevProperties(const layer_data *device_data) { 60996a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski return &device_data->phys_dev_properties; 61006a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski} 61016a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski 610289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo, 610389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkImage *pImage) { 61048dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 610556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 61068dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski bool skip = PreCallValidateCreateImage(dev_data, pCreateInfo, pAllocator, pImage); 61078dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski if (!skip) { 61088dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski result = dev_data->dispatch_table.CreateImage(device, pCreateInfo, pAllocator, pImage); 61098dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski } 61105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 6111b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 6112920311b6aa5614a545cad59521770d0898a75d65Mark Lobodzinski PostCallRecordCreateImage(dev_data, pCreateInfo, pImage); 61135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 61145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 61155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 61165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 61178c07a094dc9cc4afb6b62181f341c12b9e969041Mark YoungVKAPI_ATTR VkResult VKAPI_CALL CreateImageView(VkDevice device, const VkImageViewCreateInfo *pCreateInfo, 61188c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young const VkAllocationCallbacks *pAllocator, VkImageView *pView) { 611956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 61208c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young std::unique_lock<std::mutex> lock(global_lock); 6121e3effabf8e97cae8e006477806ceaca62e4f2ce7Tobin Ehlis bool skip = PreCallValidateCreateImageView(dev_data, pCreateInfo); 61228c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young lock.unlock(); 6123cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 61244a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateImageView(device, pCreateInfo, pAllocator, pView); 61255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 61268c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young lock.lock(); 612779fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis PostCallRecordCreateImageView(dev_data, pCreateInfo, *pView); 61288c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young lock.unlock(); 61295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6130bb6624cb996175d8945190886a200e720b3871efChris Forbes 61315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 61325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 61335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6134bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateFence(VkDevice device, const VkFenceCreateInfo *pCreateInfo, 6135bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkFence *pFence) { 613656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 61374a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateFence(device, pCreateInfo, pAllocator, pFence); 61385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 6139b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 6140a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis auto &fence_node = dev_data->fenceMap[*pFence]; 61418988ad37ea5a054ff2ae3cbe4b767ae6c13cf48bChris Forbes fence_node.fence = *pFence; 6142a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis fence_node.createInfo = *pCreateInfo; 6143cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes fence_node.state = (pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT) ? FENCE_RETIRED : FENCE_UNSIGNALED; 61445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 61455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 61465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 61475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 61485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// TODO handle pipeline caches 614989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreatePipelineCache(VkDevice device, const VkPipelineCacheCreateInfo *pCreateInfo, 615089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkPipelineCache *pPipelineCache) { 615156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 61524a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreatePipelineCache(device, pCreateInfo, pAllocator, pPipelineCache); 61535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 61545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 61555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6156bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyPipelineCache(VkDevice device, VkPipelineCache pipelineCache, 6157bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator) { 615856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 61594a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyPipelineCache(device, pipelineCache, pAllocator); 61605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 61615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6162bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL GetPipelineCacheData(VkDevice device, VkPipelineCache pipelineCache, size_t *pDataSize, 6163bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski void *pData) { 616456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 61654a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.GetPipelineCacheData(device, pipelineCache, pDataSize, pData); 61665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 61675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 61685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6169bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL MergePipelineCaches(VkDevice device, VkPipelineCache dstCache, uint32_t srcCacheCount, 6170bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkPipelineCache *pSrcCaches) { 617156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 61724a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.MergePipelineCaches(device, dstCache, srcCacheCount, pSrcCaches); 61735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 61745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 61755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 61763d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis// utility function to set collective state for pipeline 61774c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlisvoid set_pipeline_state(PIPELINE_STATE *pPipe) { 61783d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis // If any attachment used by this pipeline has blendEnable, set top-level blendEnable 61793d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis if (pPipe->graphicsPipelineCI.pColorBlendState) { 61803d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis for (size_t i = 0; i < pPipe->attachments.size(); ++i) { 61813d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis if (VK_TRUE == pPipe->attachments[i].blendEnable) { 61823d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis if (((pPipe->attachments[i].dstAlphaBlendFactor >= VK_BLEND_FACTOR_CONSTANT_COLOR) && 61833d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis (pPipe->attachments[i].dstAlphaBlendFactor <= VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA)) || 61843d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis ((pPipe->attachments[i].dstColorBlendFactor >= VK_BLEND_FACTOR_CONSTANT_COLOR) && 61853d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis (pPipe->attachments[i].dstColorBlendFactor <= VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA)) || 61863d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis ((pPipe->attachments[i].srcAlphaBlendFactor >= VK_BLEND_FACTOR_CONSTANT_COLOR) && 61873d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis (pPipe->attachments[i].srcAlphaBlendFactor <= VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA)) || 61883d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis ((pPipe->attachments[i].srcColorBlendFactor >= VK_BLEND_FACTOR_CONSTANT_COLOR) && 61893d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis (pPipe->attachments[i].srcColorBlendFactor <= VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA))) { 61903d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis pPipe->blendConstantsEnabled = true; 61913d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 61923d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 61933d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 61943d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 61953d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis} 61963d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis 619748b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinskistatic bool PreCallCreateGraphicsPipelines(layer_data *device_data, uint32_t count, 619848b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinski const VkGraphicsPipelineCreateInfo *create_infos, vector<PIPELINE_STATE *> &pipe_state) { 619948b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinski bool skip = false; 6200bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski instance_layer_data *instance_data = 620156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis GetLayerDataPtr(get_dispatch_key(device_data->instance_data->instance), instance_layer_data_map); 620248b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinski 620348b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinski for (uint32_t i = 0; i < count; i++) { 620448b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinski skip |= verifyPipelineCreateState(device_data, pipe_state, i); 620578b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski if (create_infos[i].pVertexInputState != NULL) { 620678b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski for (uint32_t j = 0; j < create_infos[i].pVertexInputState->vertexAttributeDescriptionCount; j++) { 620778b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski VkFormat format = create_infos[i].pVertexInputState->pVertexAttributeDescriptions[j].format; 620878b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski // Internal call to get format info. Still goes through layers, could potentially go directly to ICD. 620978b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski VkFormatProperties properties; 621078b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski instance_data->dispatch_table.GetPhysicalDeviceFormatProperties(device_data->physical_device, format, &properties); 621178b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski if ((properties.bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) == 0) { 621278b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski skip |= log_msg( 621378b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 621478b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski __LINE__, VALIDATION_ERROR_01413, "IMAGE", 621578b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski "vkCreateGraphicsPipelines: pCreateInfo[%d].pVertexInputState->vertexAttributeDescriptions[%d].format " 621678b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski "(%s) is not a supported vertex buffer format. %s", 621778b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski i, j, string_VkFormat(format), validation_error_map[VALIDATION_ERROR_01413]); 621878b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski } 621978b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski } 622078b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski } 622148b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinski } 622248b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinski return skip; 622348b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinski} 622448b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinski 6225bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count, 6226bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkGraphicsPipelineCreateInfo *pCreateInfos, 6227bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines) { 62285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODO What to do with pipelineCache? 62295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // The order of operations here is a little convoluted but gets the job done 62304c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis // 1. Pipeline create state is first shadowed into PIPELINE_STATE struct 62315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // 2. Create state is then validated (which uses flags setup during shadowing) 62325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // 3. If everything looks good, we'll then create the pipeline and add NODE to pipelineMap 623342486a20f07b16f0c5361cdc00fd789b07b1989aMark Lobodzinski bool skip = false; 62345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODO : Improve this data struct w/ unique_ptrs so cleanup below is automatic 623542486a20f07b16f0c5361cdc00fd789b07b1989aMark Lobodzinski vector<PIPELINE_STATE *> pipe_state(count); 623656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 62375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 62385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t i = 0; 6239b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 62405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 62415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (i = 0; i < count; i++) { 624242486a20f07b16f0c5361cdc00fd789b07b1989aMark Lobodzinski pipe_state[i] = new PIPELINE_STATE; 624342486a20f07b16f0c5361cdc00fd789b07b1989aMark Lobodzinski pipe_state[i]->initGraphicsPipeline(&pCreateInfos[i]); 62449a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis pipe_state[i]->render_pass_ci.initialize(GetRenderPassState(dev_data, pCreateInfos[i].renderPass)->createInfo.ptr()); 624542486a20f07b16f0c5361cdc00fd789b07b1989aMark Lobodzinski pipe_state[i]->pipeline_layout = *getPipelineLayout(dev_data, pCreateInfos[i].layout); 62465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 624742486a20f07b16f0c5361cdc00fd789b07b1989aMark Lobodzinski skip |= PreCallCreateGraphicsPipelines(dev_data, count, pCreateInfos, pipe_state); 62485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6249c70226063be6148056ceeccf835175a1fd59f24fChris Forbes if (skip) { 6250c70226063be6148056ceeccf835175a1fd59f24fChris Forbes for (i = 0; i < count; i++) { 6251c70226063be6148056ceeccf835175a1fd59f24fChris Forbes delete pipe_state[i]; 62521ab616b32d4e5b7d62d4a8c41b0c03ea335ab845Chris Forbes pPipelines[i] = VK_NULL_HANDLE; 6253c70226063be6148056ceeccf835175a1fd59f24fChris Forbes } 62547a456d188475c23b566334be45dc0489b2789653Chris Forbes return VK_ERROR_VALIDATION_FAILED_EXT; 62557a456d188475c23b566334be45dc0489b2789653Chris Forbes } 62567a456d188475c23b566334be45dc0489b2789653Chris Forbes 62577a456d188475c23b566334be45dc0489b2789653Chris Forbes lock.unlock(); 6258bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto result = 6259bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski dev_data->dispatch_table.CreateGraphicsPipelines(device, pipelineCache, count, pCreateInfos, pAllocator, pPipelines); 62607a456d188475c23b566334be45dc0489b2789653Chris Forbes lock.lock(); 62617a456d188475c23b566334be45dc0489b2789653Chris Forbes for (i = 0; i < count; i++) { 626261943a7503bc8594338f3364ef42f1d863486c04Chris Forbes if (pPipelines[i] == VK_NULL_HANDLE) { 626361943a7503bc8594338f3364ef42f1d863486c04Chris Forbes delete pipe_state[i]; 6264bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski } else { 626561943a7503bc8594338f3364ef42f1d863486c04Chris Forbes pipe_state[i]->pipeline = pPipelines[i]; 626661943a7503bc8594338f3364ef42f1d863486c04Chris Forbes dev_data->pipelineMap[pipe_state[i]->pipeline] = pipe_state[i]; 626761943a7503bc8594338f3364ef42f1d863486c04Chris Forbes } 62685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6269c70226063be6148056ceeccf835175a1fd59f24fChris Forbes 62705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 62715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 62725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6273bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count, 6274bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkComputePipelineCreateInfo *pCreateInfos, 6275bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines) { 62760108a1af0b7c6949846e9d71d00bbfb322b6f7caChris Forbes bool skip = false; 62775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 62785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODO : Improve this data struct w/ unique_ptrs so cleanup below is automatic 62794c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis vector<PIPELINE_STATE *> pPipeState(count); 628056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 62815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 62825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t i = 0; 6283b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 62845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (i = 0; i < count; i++) { 62855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODO: Verify compute stage bits 62865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 62875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Create and initialize internal tracking data structure 62884c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis pPipeState[i] = new PIPELINE_STATE; 62894c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis pPipeState[i]->initComputePipeline(&pCreateInfos[i]); 6290c2a5a36d03bbe52f5854a5884346e4a84115e259Tobin Ehlis pPipeState[i]->pipeline_layout = *getPipelineLayout(dev_data, pCreateInfos[i].layout); 62915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 62925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODO: Add Compute Pipeline Verification 62930108a1af0b7c6949846e9d71d00bbfb322b6f7caChris Forbes skip |= !validate_compute_pipeline(dev_data->report_data, pPipeState[i], &dev_data->enabled_features, 6294bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski dev_data->shaderModuleMap); 62950108a1af0b7c6949846e9d71d00bbfb322b6f7caChris Forbes // skip |= verifyPipelineCreateState(dev_data, pPipeState[i]); 62965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 62975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 62987a456d188475c23b566334be45dc0489b2789653Chris Forbes if (skip) { 62995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (i = 0; i < count; i++) { 63005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Clean up any locally allocated data structures 63014c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis delete pPipeState[i]; 6302fcf67c021fdfcbeb12fb04daa9a69ecd7d376c5cChris Forbes pPipelines[i] = VK_NULL_HANDLE; 63035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 63045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return VK_ERROR_VALIDATION_FAILED_EXT; 63055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 63067a456d188475c23b566334be45dc0489b2789653Chris Forbes 63077a456d188475c23b566334be45dc0489b2789653Chris Forbes lock.unlock(); 6308bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto result = 6309bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski dev_data->dispatch_table.CreateComputePipelines(device, pipelineCache, count, pCreateInfos, pAllocator, pPipelines); 63107a456d188475c23b566334be45dc0489b2789653Chris Forbes lock.lock(); 63117a456d188475c23b566334be45dc0489b2789653Chris Forbes for (i = 0; i < count; i++) { 6312fcf67c021fdfcbeb12fb04daa9a69ecd7d376c5cChris Forbes if (pPipelines[i] == VK_NULL_HANDLE) { 6313fcf67c021fdfcbeb12fb04daa9a69ecd7d376c5cChris Forbes delete pPipeState[i]; 6314bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski } else { 6315fcf67c021fdfcbeb12fb04daa9a69ecd7d376c5cChris Forbes pPipeState[i]->pipeline = pPipelines[i]; 6316fcf67c021fdfcbeb12fb04daa9a69ecd7d376c5cChris Forbes dev_data->pipelineMap[pPipeState[i]->pipeline] = pPipeState[i]; 6317fcf67c021fdfcbeb12fb04daa9a69ecd7d376c5cChris Forbes } 63187a456d188475c23b566334be45dc0489b2789653Chris Forbes } 63197a456d188475c23b566334be45dc0489b2789653Chris Forbes 63205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 63215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 63225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 632389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateSampler(VkDevice device, const VkSamplerCreateInfo *pCreateInfo, 632489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkSampler *pSampler) { 632556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 63264a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateSampler(device, pCreateInfo, pAllocator, pSampler); 63275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 6328b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 6329d31a44af6da568692a73201825459689c9431867Tobin Ehlis dev_data->samplerMap[*pSampler] = unique_ptr<SAMPLER_STATE>(new SAMPLER_STATE(pSampler, pCreateInfo)); 63305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 63315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 63325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 63335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 63340c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlisstatic bool PreCallValidateCreateDescriptorSetLayout(layer_data *dev_data, const VkDescriptorSetLayoutCreateInfo *create_info) { 6335cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.create_descriptor_set_layout) return false; 63360c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis return cvdescriptorset::DescriptorSetLayout::ValidateCreateInfo(dev_data->report_data, create_info); 63370c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis} 63380c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis 63390c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlisstatic void PostCallRecordCreateDescriptorSetLayout(layer_data *dev_data, const VkDescriptorSetLayoutCreateInfo *create_info, 63400c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis VkDescriptorSetLayout set_layout) { 63413f1d2ba6852cf6b1bb4e1f06d690293565108e2cTobin Ehlis // TODO: Convert this to unique_ptr to avoid leaks 63420c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis dev_data->descriptorSetLayoutMap[set_layout] = new cvdescriptorset::DescriptorSetLayout(create_info, set_layout); 63430c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis} 63440c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis 6345bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateDescriptorSetLayout(VkDevice device, const VkDescriptorSetLayoutCreateInfo *pCreateInfo, 6346bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, 6347bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDescriptorSetLayout *pSetLayout) { 634856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 63490c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 63500c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 63510c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis bool skip = PreCallValidateCreateDescriptorSetLayout(dev_data, pCreateInfo); 63520c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis if (!skip) { 63530c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis lock.unlock(); 63540c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis result = dev_data->dispatch_table.CreateDescriptorSetLayout(device, pCreateInfo, pAllocator, pSetLayout); 63550c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis if (VK_SUCCESS == result) { 63560c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis lock.lock(); 63570c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis PostCallRecordCreateDescriptorSetLayout(dev_data, pCreateInfo, *pSetLayout); 63580c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis } 63595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 63605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 63615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 63625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 63639e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz// Used by CreatePipelineLayout and CmdPushConstants. 63649e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz// Note that the index argument is optional and only used by CreatePipelineLayout. 63659e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultzstatic bool validatePushConstantRange(const layer_data *dev_data, const uint32_t offset, const uint32_t size, 63669e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz const char *caller_name, uint32_t index = 0) { 6367cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.push_constant_range) return false; 63689e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz uint32_t const maxPushConstantsSize = dev_data->phys_dev_properties.properties.limits.maxPushConstantsSize; 636983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 63709e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz // Check that offset + size don't exceed the max. 63719e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz // Prevent arithetic overflow here by avoiding addition and testing in this order. 63729e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz if ((offset >= maxPushConstantsSize) || (size > maxPushConstantsSize - offset)) { 63739e24d8153ab63bc3ac08b5a1517c203930b5de91Karl 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. 63749e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz if (0 == strcmp(caller_name, "vkCreatePipelineLayout()")) { 6375e420dd92dcfc04f279e98796a49ee26b2c3ddafeTobin Ehlis if (offset >= maxPushConstantsSize) { 6376e420dd92dcfc04f279e98796a49ee26b2c3ddafeTobin Ehlis skip_call |= 6377e420dd92dcfc04f279e98796a49ee26b2c3ddafeTobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 6378cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VALIDATION_ERROR_00877, "DS", 6379cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s call has push constants index %u with offset %u that " 6380cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "exceeds this device's maxPushConstantSize of %u. %s", 6381e420dd92dcfc04f279e98796a49ee26b2c3ddafeTobin Ehlis caller_name, index, offset, maxPushConstantsSize, validation_error_map[VALIDATION_ERROR_00877]); 6382e420dd92dcfc04f279e98796a49ee26b2c3ddafeTobin Ehlis } 6383e420dd92dcfc04f279e98796a49ee26b2c3ddafeTobin Ehlis if (size > maxPushConstantsSize - offset) { 6384e420dd92dcfc04f279e98796a49ee26b2c3ddafeTobin Ehlis skip_call |= 6385e420dd92dcfc04f279e98796a49ee26b2c3ddafeTobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 6386cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VALIDATION_ERROR_00880, "DS", 6387cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s call has push constants index %u with offset %u and size %u that " 6388cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "exceeds this device's maxPushConstantSize of %u. %s", 6389e420dd92dcfc04f279e98796a49ee26b2c3ddafeTobin Ehlis caller_name, index, offset, size, maxPushConstantsSize, validation_error_map[VALIDATION_ERROR_00880]); 6390e420dd92dcfc04f279e98796a49ee26b2c3ddafeTobin Ehlis } 63919e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } else if (0 == strcmp(caller_name, "vkCmdPushConstants()")) { 63924527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton if (offset >= maxPushConstantsSize) { 63934527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton skip_call |= 63944527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 6395cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VALIDATION_ERROR_00991, "DS", 6396cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s call has push constants index %u with offset %u that " 6397cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "exceeds this device's maxPushConstantSize of %u. %s", 63984527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton caller_name, index, offset, maxPushConstantsSize, validation_error_map[VALIDATION_ERROR_00991]); 63994527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton } 64004527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton if (size > maxPushConstantsSize - offset) { 64014527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton skip_call |= 64024527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 6403cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VALIDATION_ERROR_00992, "DS", 6404cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s call has push constants index %u with offset %u and size %u that " 6405cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "exceeds this device's maxPushConstantSize of %u. %s", 64064527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton caller_name, index, offset, size, maxPushConstantsSize, validation_error_map[VALIDATION_ERROR_00992]); 64074527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton } 64089e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } else { 640983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 641083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis DRAWSTATE_INTERNAL_ERROR, "DS", "%s caller not supported.", caller_name); 64119e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 64129e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 64139e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz // size needs to be non-zero and a multiple of 4. 64149e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz if ((size == 0) || ((size & 0x3) != 0)) { 64159e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz if (0 == strcmp(caller_name, "vkCreatePipelineLayout()")) { 6416891f13be101e95697e5af9503f06da38b0c48f79Tobin Ehlis if (size == 0) { 6417891f13be101e95697e5af9503f06da38b0c48f79Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 6418cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, VALIDATION_ERROR_00878, "DS", 6419cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s call has push constants index %u with " 6420cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "size %u. Size must be greater than zero. %s", 6421891f13be101e95697e5af9503f06da38b0c48f79Tobin Ehlis caller_name, index, size, validation_error_map[VALIDATION_ERROR_00878]); 6422891f13be101e95697e5af9503f06da38b0c48f79Tobin Ehlis } 6423891f13be101e95697e5af9503f06da38b0c48f79Tobin Ehlis if (size & 0x3) { 6424891f13be101e95697e5af9503f06da38b0c48f79Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 6425cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, VALIDATION_ERROR_00879, "DS", 6426cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s call has push constants index %u with " 6427cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "size %u. Size must be a multiple of 4. %s", 6428891f13be101e95697e5af9503f06da38b0c48f79Tobin Ehlis caller_name, index, size, validation_error_map[VALIDATION_ERROR_00879]); 6429891f13be101e95697e5af9503f06da38b0c48f79Tobin Ehlis } 64309e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } else if (0 == strcmp(caller_name, "vkCmdPushConstants()")) { 64314527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton if (size == 0) { 64324527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 6433cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, VALIDATION_ERROR_01000, "DS", 6434cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s call has push constants index %u with " 6435cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "size %u. Size must be greater than zero. %s", 64364527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton caller_name, index, size, validation_error_map[VALIDATION_ERROR_01000]); 64374527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton } 64384527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton if (size & 0x3) { 64394527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 6440cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, VALIDATION_ERROR_00990, "DS", 6441cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s call has push constants index %u with " 6442cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "size %u. Size must be a multiple of 4. %s", 64434527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton caller_name, index, size, validation_error_map[VALIDATION_ERROR_00990]); 64444527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton } 64459e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } else { 644683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 644783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis DRAWSTATE_INTERNAL_ERROR, "DS", "%s caller not supported.", caller_name); 64489e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 64499e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 64509e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz // offset needs to be a multiple of 4. 64519e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz if ((offset & 0x3) != 0) { 64529e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz if (0 == strcmp(caller_name, "vkCreatePipelineLayout()")) { 645383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 6454cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VALIDATION_ERROR_02521, "DS", 6455cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s call has push constants index %u with " 6456cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "offset %u. Offset must be a multiple of 4. %s", 64574527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton caller_name, index, offset, validation_error_map[VALIDATION_ERROR_02521]); 64589e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } else if (0 == strcmp(caller_name, "vkCmdPushConstants()")) { 645983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 6460cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VALIDATION_ERROR_00989, "DS", 6461cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s call has push constants with " 6462cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "offset %u. Offset must be a multiple of 4. %s", 64634527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton caller_name, offset, validation_error_map[VALIDATION_ERROR_00989]); 64649e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } else { 646583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 646683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis DRAWSTATE_INTERNAL_ERROR, "DS", "%s caller not supported.", caller_name); 64679e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 64685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 646983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis return skip_call; 64705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 64715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6472bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo, 647389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout) { 647483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 647556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 64761c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis // TODO : Add checks for VALIDATION_ERRORS 865-871 64779e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz // Push Constant Range checks 647807a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz uint32_t i, j; 64795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (i = 0; i < pCreateInfo->pushConstantRangeCount; ++i) { 648083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= validatePushConstantRange(dev_data, pCreateInfo->pPushConstantRanges[i].offset, 648183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis pCreateInfo->pPushConstantRanges[i].size, "vkCreatePipelineLayout()", i); 64829e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz if (0 == pCreateInfo->pPushConstantRanges[i].stageFlags) { 648383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 64844527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton VALIDATION_ERROR_00882, "DS", "vkCreatePipelineLayout() call has no stageFlags set. %s", 64854527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton validation_error_map[VALIDATION_ERROR_00882]); 64869e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 64879e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 6488cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip_call) return VK_ERROR_VALIDATION_FAILED_EXT; 648907a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz 64909e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz // Each range has been validated. Now check for overlap between ranges (if they are good). 649107a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz // There's no explicit Valid Usage language against this, so issue a warning instead of an error. 649207a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz for (i = 0; i < pCreateInfo->pushConstantRangeCount; ++i) { 649307a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz for (j = i + 1; j < pCreateInfo->pushConstantRangeCount; ++j) { 649407a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz const uint32_t minA = pCreateInfo->pPushConstantRanges[i].offset; 649507a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz const uint32_t maxA = minA + pCreateInfo->pPushConstantRanges[i].size; 649607a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz const uint32_t minB = pCreateInfo->pPushConstantRanges[j].offset; 649707a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz const uint32_t maxB = minB + pCreateInfo->pPushConstantRanges[j].size; 649807a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz if ((minA <= minB && maxA > minB) || (minB <= minA && maxB > minA)) { 6499cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 6500cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, DRAWSTATE_PUSH_CONSTANTS_ERROR, "DS", 6501cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkCreatePipelineLayout() call has push constants with " 6502cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "overlapping ranges: %u:[%u, %u), %u:[%u, %u)", 6503cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski i, minA, maxA, j, minB, maxB); 65049e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 65055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 65065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6507f73b2046273413ea1338dd714d67c39f8e0fa09eChris Forbes 65084a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout); 65095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 6510b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 65115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis PIPELINE_LAYOUT_NODE &plNode = dev_data->pipelineLayoutMap[*pPipelineLayout]; 651269b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis plNode.layout = *pPipelineLayout; 6513416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis plNode.set_layouts.resize(pCreateInfo->setLayoutCount); 65145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (i = 0; i < pCreateInfo->setLayoutCount; ++i) { 65159a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis plNode.set_layouts[i] = GetDescriptorSetLayout(dev_data, pCreateInfo->pSetLayouts[i]); 65165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6517416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis plNode.push_constant_ranges.resize(pCreateInfo->pushConstantRangeCount); 65185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (i = 0; i < pCreateInfo->pushConstantRangeCount; ++i) { 6519416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis plNode.push_constant_ranges[i] = pCreateInfo->pPushConstantRanges[i]; 65205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 65215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 65225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 65235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 65245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6525bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateDescriptorPool(VkDevice device, const VkDescriptorPoolCreateInfo *pCreateInfo, 6526bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkDescriptorPool *pDescriptorPool) { 652756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 65284a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateDescriptorPool(device, pCreateInfo, pAllocator, pDescriptorPool); 65295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 65305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, 6531414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller (uint64_t)*pDescriptorPool, __LINE__, DRAWSTATE_OUT_OF_MEMORY, "DS", "Created Descriptor Pool 0x%" PRIxLEAST64, 65325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (uint64_t)*pDescriptorPool)) 65335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return VK_ERROR_VALIDATION_FAILED_EXT; 6534a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis DESCRIPTOR_POOL_STATE *pNewNode = new DESCRIPTOR_POOL_STATE(*pDescriptorPool, pCreateInfo); 65355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (NULL == pNewNode) { 65365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, 65375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (uint64_t)*pDescriptorPool, __LINE__, DRAWSTATE_OUT_OF_MEMORY, "DS", 6538a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis "Out of memory while attempting to allocate DESCRIPTOR_POOL_STATE in vkCreateDescriptorPool()")) 65395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return VK_ERROR_VALIDATION_FAILED_EXT; 65405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 6541b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 65425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->descriptorPoolMap[*pDescriptorPool] = pNewNode; 65435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 65445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 65455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Need to do anything if pool create fails? 65465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 65475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 65485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 65495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6550bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL ResetDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, 6551bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDescriptorPoolResetFlags flags) { 65527286e20c06011d3c6fa7edfbdbadd42bb6e8cc35Tobin Ehlis // TODO : Add checks for VALIDATION_ERROR_00928 655356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 65544a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.ResetDescriptorPool(device, descriptorPool, flags); 65555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 6556b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 65575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis clearDescriptorPool(dev_data, device, descriptorPool, flags); 65585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 65595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 65605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 65612c4e180a4442f968b44f3d5136f7ffda706f6428Chris Forbes// Ensure the pool contains enough descriptors and descriptor sets to satisfy 6562789832b514862c7a7b5b847eeb8e7cacb733b77bTobin Ehlis// an allocation request. Fills common_data with the total number of descriptors of each type required, 6563789832b514862c7a7b5b847eeb8e7cacb733b77bTobin Ehlis// as well as DescriptorSetLayout ptrs used for later update. 65647f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlisstatic bool PreCallValidateAllocateDescriptorSets(layer_data *dev_data, const VkDescriptorSetAllocateInfo *pAllocateInfo, 65657f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlis cvdescriptorset::AllocateDescriptorSetsData *common_data) { 6566cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.allocate_descriptor_sets) return false; 65677e73e5c6b3020b96a821985f73012f2af0f1b992Tobin Ehlis // All state checks for AllocateDescriptorSets is done in single function 6568e3f7c45fd64a44a67ce96c89e2bbee426c6ecf24Tobin Ehlis return cvdescriptorset::ValidateAllocateDescriptorSets(dev_data->report_data, pAllocateInfo, dev_data, common_data); 65697e73e5c6b3020b96a821985f73012f2af0f1b992Tobin Ehlis} 65707e73e5c6b3020b96a821985f73012f2af0f1b992Tobin Ehlis// Allocation state was good and call down chain was made so update state based on allocating descriptor sets 65717e73e5c6b3020b96a821985f73012f2af0f1b992Tobin Ehlisstatic void PostCallRecordAllocateDescriptorSets(layer_data *dev_data, const VkDescriptorSetAllocateInfo *pAllocateInfo, 65727f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlis VkDescriptorSet *pDescriptorSets, 65737f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlis const cvdescriptorset::AllocateDescriptorSetsData *common_data) { 65747e73e5c6b3020b96a821985f73012f2af0f1b992Tobin Ehlis // All the updates are contained in a single cvdescriptorset function 65752c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis cvdescriptorset::PerformAllocateDescriptorSets(pAllocateInfo, pDescriptorSets, common_data, &dev_data->descriptorPoolMap, 6576b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis &dev_data->setMap, dev_data); 65772c4e180a4442f968b44f3d5136f7ffda706f6428Chris Forbes} 65782c4e180a4442f968b44f3d5136f7ffda706f6428Chris Forbes 6579bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL AllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo *pAllocateInfo, 6580bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDescriptorSet *pDescriptorSets) { 658156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 6582b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 65837f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlis cvdescriptorset::AllocateDescriptorSetsData common_data(pAllocateInfo->descriptorSetCount); 65847f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlis bool skip_call = PreCallValidateAllocateDescriptorSets(dev_data, pAllocateInfo, &common_data); 6585b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 6586d173e0daab123373ce75105f2a908f6ae7cef6abChris Forbes 6587cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip_call) return VK_ERROR_VALIDATION_FAILED_EXT; 6588d173e0daab123373ce75105f2a908f6ae7cef6abChris Forbes 65894a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.AllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets); 65906511ce241f7f210211e0c0e882f3c14889071f4dChris Forbes 65915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 6592b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.lock(); 65937f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlis PostCallRecordAllocateDescriptorSets(dev_data, pAllocateInfo, pDescriptorSets, &common_data); 6594b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 65955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 65965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 65975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 6598cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis// Verify state before freeing DescriptorSets 6599cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlisstatic bool PreCallValidateFreeDescriptorSets(const layer_data *dev_data, VkDescriptorPool pool, uint32_t count, 6600cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis const VkDescriptorSet *descriptor_sets) { 6601cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.free_descriptor_sets) return false; 6602cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis bool skip_call = false; 6603cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis // First make sure sets being destroyed are not currently in-use 6604405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour for (uint32_t i = 0; i < count; ++i) { 6605405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (descriptor_sets[i] != VK_NULL_HANDLE) { 6606405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour skip_call |= validateIdleDescriptorSet(dev_data, descriptor_sets[i], "vkFreeDescriptorSets"); 6607405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 6608405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 6609cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis 66109a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DESCRIPTOR_POOL_STATE *pool_state = GetDescriptorPoolState(dev_data, pool); 6611a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis if (pool_state && !(VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT & pool_state->createInfo.flags)) { 6612cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis // Can't Free from a NON_FREE pool 6613cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, 66141c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis reinterpret_cast<uint64_t &>(pool), __LINE__, VALIDATION_ERROR_00922, "DS", 6615cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis "It is invalid to call vkFreeDescriptorSets() with a pool created without setting " 66161c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis "VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT. %s", 66171c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis validation_error_map[VALIDATION_ERROR_00922]); 6618cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis } 6619cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis return skip_call; 6620cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis} 6621cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis// Sets have been removed from the pool so update underlying state 6622cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlisstatic void PostCallRecordFreeDescriptorSets(layer_data *dev_data, VkDescriptorPool pool, uint32_t count, 6623cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis const VkDescriptorSet *descriptor_sets) { 66249a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DESCRIPTOR_POOL_STATE *pool_state = GetDescriptorPoolState(dev_data, pool); 6625cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis // Update available descriptor sets in pool 6626cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis pool_state->availableSets += count; 6627cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis 6628cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis // For each freed descriptor add its resources back into the pool as available and remove from pool and setMap 6629cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis for (uint32_t i = 0; i < count; ++i) { 6630405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (descriptor_sets[i] != VK_NULL_HANDLE) { 6631405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour auto descriptor_set = dev_data->setMap[descriptor_sets[i]]; 6632405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour uint32_t type_index = 0, descriptor_count = 0; 6633405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour for (uint32_t j = 0; j < descriptor_set->GetBindingCount(); ++j) { 6634405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour type_index = static_cast<uint32_t>(descriptor_set->GetTypeFromIndex(j)); 6635405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour descriptor_count = descriptor_set->GetDescriptorCountFromIndex(j); 6636405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour pool_state->availableDescriptorTypeCount[type_index] += descriptor_count; 6637405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 6638405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour freeDescriptorSet(dev_data, descriptor_set); 6639405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour pool_state->sets.erase(descriptor_set); 6640405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 6641cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis } 6642cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis} 66435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6644bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL FreeDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool, uint32_t count, 6645bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkDescriptorSet *pDescriptorSets) { 664656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 66475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Make sure that no sets being destroyed are in-flight 6648b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 664983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = PreCallValidateFreeDescriptorSets(dev_data, descriptorPool, count, pDescriptorSets); 6650b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 6651e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis 6652cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip_call) return VK_ERROR_VALIDATION_FAILED_EXT; 66534a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.FreeDescriptorSets(device, descriptorPool, count, pDescriptorSets); 66545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 6655b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.lock(); 6656cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis PostCallRecordFreeDescriptorSets(dev_data, descriptorPool, count, pDescriptorSets); 6657b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 66585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 66595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 66605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 66616b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis// TODO : This is a Proof-of-concept for core validation architecture 66626b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis// Really we'll want to break out these functions to separate files but 66636b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis// keeping it all together here to prove out design 66646b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis// PreCallValidate* handles validating all of the state prior to calling down chain to UpdateDescriptorSets() 66656b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlisstatic bool PreCallValidateUpdateDescriptorSets(layer_data *dev_data, uint32_t descriptorWriteCount, 66666b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis const VkWriteDescriptorSet *pDescriptorWrites, uint32_t descriptorCopyCount, 66676b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis const VkCopyDescriptorSet *pDescriptorCopies) { 6668cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.update_descriptor_sets) return false; 66696b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis // First thing to do is perform map look-ups. 66706b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis // NOTE : UpdateDescriptorSets is somewhat unique in that it's operating on a number of DescriptorSets 66716b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis // so we can't just do a single map look-up up-front, but do them individually in functions below 66726b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis 66736b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis // Now make call(s) that validate state, but don't perform state updates in this function 66746b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis // Note, here DescriptorSets is unique in that we don't yet have an instance. Using a helper function in the 66756b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis // namespace which will parse params and make calls into specific class instances 6676104ab082916e41467ef60baaab7a5a8b2e02c59cTobin Ehlis return cvdescriptorset::ValidateUpdateDescriptorSets(dev_data->report_data, dev_data, descriptorWriteCount, pDescriptorWrites, 6677104ab082916e41467ef60baaab7a5a8b2e02c59cTobin Ehlis descriptorCopyCount, pDescriptorCopies); 66786b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis} 66796b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis// PostCallRecord* handles recording state updates following call down chain to UpdateDescriptorSets() 66806b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlisstatic void PostCallRecordUpdateDescriptorSets(layer_data *dev_data, uint32_t descriptorWriteCount, 66816b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis const VkWriteDescriptorSet *pDescriptorWrites, uint32_t descriptorCopyCount, 66826b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis const VkCopyDescriptorSet *pDescriptorCopies) { 6683104ab082916e41467ef60baaab7a5a8b2e02c59cTobin Ehlis cvdescriptorset::PerformUpdateDescriptorSets(dev_data, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, 66846b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis pDescriptorCopies); 66856b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis} 66865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6687bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL UpdateDescriptorSets(VkDevice device, uint32_t descriptorWriteCount, 6688bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkWriteDescriptorSet *pDescriptorWrites, uint32_t descriptorCopyCount, 6689bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkCopyDescriptorSet *pDescriptorCopies) { 66906b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis // Only map look-up at top level is for device-level layer_data 669156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 6692b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 66936b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis bool skip_call = PreCallValidateUpdateDescriptorSets(dev_data, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, 66946b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis pDescriptorCopies); 6695b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 66966b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis if (!skip_call) { 66974a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.UpdateDescriptorSets(device, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, 66984a0754042cf090e131e9e769d8a3633c228625beChris Forbes pDescriptorCopies); 66996b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis lock.lock(); 67006b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis // Since UpdateDescriptorSets() is void, nothing to check prior to updating state 67016b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis PostCallRecordUpdateDescriptorSets(dev_data, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, 67026b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis pDescriptorCopies); 67035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 67045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 67055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6706bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL AllocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo *pCreateInfo, 6707bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkCommandBuffer *pCommandBuffer) { 670856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 67094a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.AllocateCommandBuffers(device, pCreateInfo, pCommandBuffer); 67105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 6711b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 67129a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pPool = GetCommandPoolNode(dev_data, pCreateInfo->commandPool); 6713cd9a648074f67a1d44c15a056b90fc66da8ead17Chris Forbes 6714cd9a648074f67a1d44c15a056b90fc66da8ead17Chris Forbes if (pPool) { 671572d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis for (uint32_t i = 0; i < pCreateInfo->commandBufferCount; i++) { 67165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Add command buffer to its commandPool map 6717cd9a648074f67a1d44c15a056b90fc66da8ead17Chris Forbes pPool->commandBuffers.push_back(pCommandBuffer[i]); 67185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis GLOBAL_CB_NODE *pCB = new GLOBAL_CB_NODE; 67195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Add command buffer to map 67205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->commandBufferMap[pCommandBuffer[i]] = pCB; 67215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis resetCB(dev_data, pCommandBuffer[i]); 67225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->createInfo = *pCreateInfo; 67235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->device = device; 67245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 67255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6726b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 67275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 67285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 67295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 67305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6731883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis// Add bindings between the given cmd buffer & framebuffer and the framebuffer's children 6732c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlisstatic void AddFramebufferBinding(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, FRAMEBUFFER_STATE *fb_state) { 67330245b74a083d2cb3b083571deb0fe13b4ab428a4Tobin Ehlis addCommandBufferBinding(&fb_state->cb_bindings, 67340245b74a083d2cb3b083571deb0fe13b4ab428a4Tobin Ehlis {reinterpret_cast<uint64_t &>(fb_state->framebuffer), VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT}, 67350245b74a083d2cb3b083571deb0fe13b4ab428a4Tobin Ehlis cb_state); 6736883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis for (auto attachment : fb_state->attachments) { 6737883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis auto view_state = attachment.view_state; 6738883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis if (view_state) { 673903ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis AddCommandBufferBindingImageView(dev_data, cb_state, view_state); 6740883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis } 67419a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto rp_state = GetRenderPassState(dev_data, fb_state->createInfo.renderPass); 6742883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis if (rp_state) { 6743883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis addCommandBufferBinding( 6744883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis &rp_state->cb_bindings, 6745883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis {reinterpret_cast<uint64_t &>(rp_state->renderPass), VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT}, cb_state); 6746883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis } 6747883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis } 6748883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis} 6749883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis 6750bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL BeginCommandBuffer(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo *pBeginInfo) { 675183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 675256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 6753b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 67545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Validate command buffer level 67559a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *cb_node = GetCBNode(dev_data, commandBuffer); 6756f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis if (cb_node) { 67575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // This implicitly resets the Cmd Buffer so make sure any fence is done and then clear memory references 6758a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis if (dev_data->globalInFlightCmdBuffers.count(commandBuffer)) { 675983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= 6760a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 67614527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton (uint64_t)commandBuffer, __LINE__, VALIDATION_ERROR_00104, "MEM", 6762d79335137b414d5f89284a9ab3e014beb4ada3ebMike Weiblen "Calling vkBeginCommandBuffer() on active command buffer 0x%p before it has completed. " 67634527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton "You must check command buffer fence before this call. %s", 67644527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton commandBuffer, validation_error_map[VALIDATION_ERROR_00104]); 67655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6766f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis clear_cmd_buf_and_mem_references(dev_data, cb_node); 6767f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis if (cb_node->createInfo.level != VK_COMMAND_BUFFER_LEVEL_PRIMARY) { 67685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Secondary Command Buffer 67695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkCommandBufferInheritanceInfo *pInfo = pBeginInfo->pInheritanceInfo; 67705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!pInfo) { 677183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= 67725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 67734527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton reinterpret_cast<uint64_t>(commandBuffer), __LINE__, VALIDATION_ERROR_00106, "DS", 6774bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "vkBeginCommandBuffer(): Secondary Command Buffer (0x%p) must have inheritance info. %s", commandBuffer, 6775bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski validation_error_map[VALIDATION_ERROR_00106]); 67765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 67775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pBeginInfo->flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT) { 67782c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis // Object_tracker makes sure these objects are valid 67792c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis assert(pInfo->renderPass); 67802c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis assert(pInfo->framebuffer); 67812c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis string errorString = ""; 67829a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto framebuffer = GetFramebufferState(dev_data, pInfo->framebuffer); 67832c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis if (framebuffer) { 67842c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis if ((framebuffer->createInfo.renderPass != pInfo->renderPass) && 67852c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis !verify_renderpass_compatibility(dev_data, framebuffer->renderPassCreateInfo.ptr(), 67869a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GetRenderPassState(dev_data, pInfo->renderPass)->createInfo.ptr(), 67872c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis errorString)) { 67882c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis // renderPass that framebuffer was created with must be compatible with local renderPass 67892c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 67902c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 67912c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis reinterpret_cast<uint64_t>(commandBuffer), __LINE__, VALIDATION_ERROR_00112, "DS", 67922c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis "vkBeginCommandBuffer(): Secondary Command " 6793cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Buffer (0x%p) renderPass (0x%" PRIxLEAST64 6794cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ") is incompatible w/ framebuffer " 67952c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis "(0x%" PRIxLEAST64 ") w/ render pass (0x%" PRIxLEAST64 ") due to: %s. %s", 67962c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis commandBuffer, reinterpret_cast<const uint64_t &>(pInfo->renderPass), 67972c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis reinterpret_cast<const uint64_t &>(pInfo->framebuffer), 67982c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis reinterpret_cast<uint64_t &>(framebuffer->createInfo.renderPass), 67992c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis errorString.c_str(), validation_error_map[VALIDATION_ERROR_00112]); 68005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 68012c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis // Connect this framebuffer and its children to this cmdBuffer 68022c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis AddFramebufferBinding(dev_data, cb_node, framebuffer); 68035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 68045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 68054527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton if ((pInfo->occlusionQueryEnable == VK_FALSE || dev_data->enabled_features.occlusionQueryPrecise == VK_FALSE) && 68065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (pInfo->queryFlags & VK_QUERY_CONTROL_PRECISE_BIT)) { 680783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 680883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t>(commandBuffer), 68094527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton __LINE__, VALIDATION_ERROR_00107, "DS", 681083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis "vkBeginCommandBuffer(): Secondary Command Buffer (0x%p) must not have " 681183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis "VK_QUERY_CONTROL_PRECISE_BIT if occulusionQuery is disabled or the device does not " 68124527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton "support precise occlusion queries. %s", 68134527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton commandBuffer, validation_error_map[VALIDATION_ERROR_00107]); 68145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 68155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 68165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pInfo && pInfo->renderPass != VK_NULL_HANDLE) { 68179a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto renderPass = GetRenderPassState(dev_data, pInfo->renderPass); 681816387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes if (renderPass) { 6819fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes if (pInfo->subpass >= renderPass->createInfo.subpassCount) { 682083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg( 6821bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 6822bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski (uint64_t)commandBuffer, __LINE__, VALIDATION_ERROR_00111, "DS", 68234527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton "vkBeginCommandBuffer(): Secondary Command Buffers (0x%p) must have a subpass index (%d) " 68244527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton "that is less than the number of subpasses (%d). %s", 68254527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton commandBuffer, pInfo->subpass, renderPass->createInfo.subpassCount, 68264527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton validation_error_map[VALIDATION_ERROR_00111]); 68275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 68285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 68295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 68305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6831f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis if (CB_RECORDING == cb_node->state) { 6832cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski skip_call |= 6833cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 6834cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski (uint64_t)commandBuffer, __LINE__, VALIDATION_ERROR_00103, "DS", 6835cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkBeginCommandBuffer(): Cannot call Begin on command buffer (0x%p" 6836cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ") in the RECORDING state. Must first call vkEndCommandBuffer(). %s", 6837cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski commandBuffer, validation_error_map[VALIDATION_ERROR_00103]); 6838347d4d3139a1e743ed85bd375c20fd35bbe68d74Chris Forbes } else if (CB_RECORDED == cb_node->state || (CB_INVALID == cb_node->state && CMD_END == cb_node->last_cmd)) { 6839f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis VkCommandPool cmdPool = cb_node->createInfo.commandPool; 68409a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pPool = GetCommandPoolNode(dev_data, cmdPool); 6841cd9a648074f67a1d44c15a056b90fc66da8ead17Chris Forbes if (!(VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT & pPool->createFlags)) { 684283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= 68435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 68444527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton (uint64_t)commandBuffer, __LINE__, VALIDATION_ERROR_00105, "DS", 6845226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "Call to vkBeginCommandBuffer() on command buffer (0x%p" 6846414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller ") attempts to implicitly reset cmdBuffer created from command pool (0x%" PRIxLEAST64 68474527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton ") that does NOT have the VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT bit set. %s", 68484527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton commandBuffer, (uint64_t)cmdPool, validation_error_map[VALIDATION_ERROR_00105]); 68495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 68505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis resetCB(dev_data, commandBuffer); 68515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 68525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Set updated state here in case implicit reset occurs above 6853f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->state = CB_RECORDING; 6854f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->beginInfo = *pBeginInfo; 6855f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis if (cb_node->beginInfo.pInheritanceInfo) { 6856f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->inheritanceInfo = *(cb_node->beginInfo.pInheritanceInfo); 6857f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->beginInfo.pInheritanceInfo = &cb_node->inheritanceInfo; 6858888e1d268098177fde4a2263e3d7b7cc415f1debMark Young // If we are a secondary command-buffer and inheriting. Update the items we should inherit. 6859f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis if ((cb_node->createInfo.level != VK_COMMAND_BUFFER_LEVEL_PRIMARY) && 6860f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis (cb_node->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT)) { 68619a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis cb_node->activeRenderPass = GetRenderPassState(dev_data, cb_node->beginInfo.pInheritanceInfo->renderPass); 6862f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->activeSubpass = cb_node->beginInfo.pInheritanceInfo->subpass; 6863350841afb70bf8dcfc3c6ec6b66f0aaa639553a3Tobin Ehlis cb_node->activeFramebuffer = cb_node->beginInfo.pInheritanceInfo->framebuffer; 6864f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->framebuffers.insert(cb_node->beginInfo.pInheritanceInfo->framebuffer); 6865888e1d268098177fde4a2263e3d7b7cc415f1debMark Young } 68665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 68675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6868b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 686983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis if (skip_call) { 68705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return VK_ERROR_VALIDATION_FAILED_EXT; 68715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 68724a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.BeginCommandBuffer(commandBuffer, pBeginInfo); 6873400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis 68745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 68755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 68765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 687789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL EndCommandBuffer(VkCommandBuffer commandBuffer) { 687883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 68795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkResult result = VK_SUCCESS; 688056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 6881b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 68829a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 68835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 68844527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton if ((VK_COMMAND_BUFFER_LEVEL_PRIMARY == pCB->createInfo.level) || 68854527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton !(pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT)) { 6886fd61966f8d41b5bce15620b70563b7864cbb28feCody Northrop // This needs spec clarification to update valid usage, see comments in PR: 6887fd61966f8d41b5bce15620b70563b7864cbb28feCody Northrop // https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/pull/516#discussion_r63013756 6888ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen skip_call |= insideRenderPass(dev_data, pCB, "vkEndCommandBuffer()", VALIDATION_ERROR_00123); 6889fd61966f8d41b5bce15620b70563b7864cbb28feCody Northrop } 689029f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_END, "vkEndCommandBuffer()"); 68911ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_END); 68925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto query : pCB->activeQueries) { 689383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 68944527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton VALIDATION_ERROR_00124, "DS", 68954527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton "Ending command buffer with in progress query: queryPool 0x%" PRIx64 ", index %d. %s", 68964527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton (uint64_t)(query.pool), query.index, validation_error_map[VALIDATION_ERROR_00124]); 68975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 68985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 689983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis if (!skip_call) { 6900b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 69014a0754042cf090e131e9e769d8a3633c228625beChris Forbes result = dev_data->dispatch_table.EndCommandBuffer(commandBuffer); 6902b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.lock(); 69035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 69045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->state = CB_RECORDED; 69055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Reset CB status flags 69065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->status = 0; 69075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 69085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 69095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis result = VK_ERROR_VALIDATION_FAILED_EXT; 69105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6911b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 69125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 69135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 69145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6915bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL ResetCommandBuffer(VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags) { 6916bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis bool skip_call = false; 691756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 6918b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 69199a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 69205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkCommandPool cmdPool = pCB->createInfo.commandPool; 69219a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pPool = GetCommandPoolNode(dev_data, cmdPool); 6922cd9a648074f67a1d44c15a056b90fc66da8ead17Chris Forbes if (!(VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT & pPool->createFlags)) { 6923bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 69244527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton (uint64_t)commandBuffer, __LINE__, VALIDATION_ERROR_00093, "DS", 6925226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "Attempt to reset command buffer (0x%p) created from command pool (0x%" PRIxLEAST64 69264527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton ") that does NOT have the VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT bit set. %s", 69274527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton commandBuffer, (uint64_t)cmdPool, validation_error_map[VALIDATION_ERROR_00093]); 69285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6929cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlis skip_call |= checkCommandBufferInFlight(dev_data, pCB, "reset", VALIDATION_ERROR_00092); 6930b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 6931cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip_call) return VK_ERROR_VALIDATION_FAILED_EXT; 69324a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.ResetCommandBuffer(commandBuffer, flags); 69335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 6934b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.lock(); 6935a964cad279f9749cd9ebfc7555247ff3bff26d53Chris Forbes dev_data->globalInFlightCmdBuffers.erase(commandBuffer); 69365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis resetCB(dev_data, commandBuffer); 6937b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 69385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 69395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 69405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 694193c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski 6942bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBindPipeline(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, 6943bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkPipeline pipeline) { 6944e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis bool skip = false; 694556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 6946b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 69479a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer); 6948e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis if (cb_state) { 694929f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip |= ValidateCmd(dev_data, cb_state, CMD_BINDPIPELINE, "vkCmdBindPipeline()"); 69501ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(cb_state, CMD_BINDPIPELINE); 6951e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis if ((VK_PIPELINE_BIND_POINT_COMPUTE == pipelineBindPoint) && (cb_state->activeRenderPass)) { 6952e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis skip |= 69535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 69545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (uint64_t)pipeline, __LINE__, DRAWSTATE_INVALID_RENDERPASS_CMD, "DS", 6955414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller "Incorrectly binding compute pipeline (0x%" PRIxLEAST64 ") during active RenderPass (0x%" PRIxLEAST64 ")", 6956e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis (uint64_t)pipeline, (uint64_t)cb_state->activeRenderPass->renderPass); 69575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 69584527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton // TODO: VALIDATION_ERROR_00594 VALIDATION_ERROR_00596 69595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6960e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis PIPELINE_STATE *pipe_state = getPipelineState(dev_data, pipeline); 6961e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis if (pipe_state) { 6962e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis cb_state->lastBound[pipelineBindPoint].pipeline_state = pipe_state; 6963e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis set_cb_pso_status(cb_state, pipe_state); 6964e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis set_pipeline_state(pipe_state); 69655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 6966e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 69674527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton (uint64_t)pipeline, __LINE__, VALIDATION_ERROR_00600, "DS", 69684527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton "Attempt to bind Pipeline 0x%" PRIxLEAST64 " that doesn't exist! %s", (uint64_t)(pipeline), 69694527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton validation_error_map[VALIDATION_ERROR_00600]); 6970e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis } 6971e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis addCommandBufferBinding(&pipe_state->cb_bindings, 6972e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis {reinterpret_cast<uint64_t &>(pipeline), VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT}, cb_state); 6973e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis if (VK_PIPELINE_BIND_POINT_GRAPHICS == pipelineBindPoint) { 6974e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis // Add binding for child renderpass 69759a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto rp_state = GetRenderPassState(dev_data, pipe_state->graphicsPipelineCI.renderPass); 6976e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis if (rp_state) { 6977e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis addCommandBufferBinding( 6978e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis &rp_state->cb_bindings, 6979e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis {reinterpret_cast<uint64_t &>(rp_state->renderPass), VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT}, cb_state); 6980e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis } 69815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 69825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6983b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 6984cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdBindPipeline(commandBuffer, pipelineBindPoint, pipeline); 69855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 69865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6987bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetViewport(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, 6988bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkViewport *pViewports) { 698983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 699056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 6991b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 69929a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 69935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 699429f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_SETVIEWPORTSTATE, "vkCmdSetViewport()"); 69951ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETVIEWPORTSTATE); 6996bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pCB->viewportMask |= ((1u << viewportCount) - 1u) << firstViewport; 69975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6998b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 6999cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.CmdSetViewport(commandBuffer, firstViewport, viewportCount, pViewports); 70005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 70015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7002bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetScissor(VkCommandBuffer commandBuffer, uint32_t firstScissor, uint32_t scissorCount, 7003bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkRect2D *pScissors) { 700483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 700556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7006b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 70079a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 70085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 700929f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_SETSCISSORSTATE, "vkCmdSetScissor()"); 70101ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETSCISSORSTATE); 7011bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pCB->scissorMask |= ((1u << scissorCount) - 1u) << firstScissor; 70125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7013b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7014cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.CmdSetScissor(commandBuffer, firstScissor, scissorCount, pScissors); 70155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 70165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 701789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdSetLineWidth(VkCommandBuffer commandBuffer, float lineWidth) { 7018a27508babf63d50aea75883a3702979193c23683Mark Young bool skip_call = false; 701956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7020b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 70219a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 70225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 702329f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_SETLINEWIDTHSTATE, "vkCmdSetLineWidth()"); 70241ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETLINEWIDTHSTATE); 70255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->status |= CBSTATUS_LINE_WIDTH_SET; 7026a27508babf63d50aea75883a3702979193c23683Mark Young 70274c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis PIPELINE_STATE *pPipeTrav = pCB->lastBound[VK_PIPELINE_BIND_POINT_GRAPHICS].pipeline_state; 7028a27508babf63d50aea75883a3702979193c23683Mark Young if (pPipeTrav != NULL && !isDynamic(pPipeTrav, VK_DYNAMIC_STATE_LINE_WIDTH)) { 7029a27508babf63d50aea75883a3702979193c23683Mark Young skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 703055eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen reinterpret_cast<uint64_t &>(commandBuffer), __LINE__, VALIDATION_ERROR_01476, "DS", 7031386d9a9a77f884789a7ae4c3890aecd47132f2babaldurk "vkCmdSetLineWidth called but pipeline was created without VK_DYNAMIC_STATE_LINE_WIDTH " 703255eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen "flag. This is undefined behavior and could be ignored. %s", 703355eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen validation_error_map[VALIDATION_ERROR_01476]); 7034a27508babf63d50aea75883a3702979193c23683Mark Young } else { 7035a27508babf63d50aea75883a3702979193c23683Mark Young skip_call |= verifyLineWidth(dev_data, DRAWSTATE_INVALID_SET, reinterpret_cast<uint64_t &>(commandBuffer), lineWidth); 7036a27508babf63d50aea75883a3702979193c23683Mark Young } 70375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7038b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7039cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.CmdSetLineWidth(commandBuffer, lineWidth); 70405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 70415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7042bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetDepthBias(VkCommandBuffer commandBuffer, float depthBiasConstantFactor, float depthBiasClamp, 7043bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski float depthBiasSlopeFactor) { 704483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 704556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7046b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 70479a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 70485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 704929f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_SETDEPTHBIASSTATE, "vkCmdSetDepthBias()"); 70501ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETDEPTHBIASSTATE); 70515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->status |= CBSTATUS_DEPTH_BIAS_SET; 70525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7053b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 705483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis if (!skip_call) 70554a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdSetDepthBias(commandBuffer, depthBiasConstantFactor, depthBiasClamp, depthBiasSlopeFactor); 70565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 70575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 705889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdSetBlendConstants(VkCommandBuffer commandBuffer, const float blendConstants[4]) { 705983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 706056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7061b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 70629a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 70635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 706429f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_SETBLENDSTATE, "vkCmdSetBlendConstants()"); 70651ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETBLENDSTATE); 70663d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis pCB->status |= CBSTATUS_BLEND_CONSTANTS_SET; 70675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7068b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7069cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.CmdSetBlendConstants(commandBuffer, blendConstants); 70705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 70715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7072bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetDepthBounds(VkCommandBuffer commandBuffer, float minDepthBounds, float maxDepthBounds) { 707383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 707456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7075b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 70769a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 70775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 707829f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_SETDEPTHBOUNDSSTATE, "vkCmdSetDepthBounds()"); 70791ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETDEPTHBOUNDSSTATE); 70805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->status |= CBSTATUS_DEPTH_BOUNDS_SET; 70815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7082b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7083cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.CmdSetDepthBounds(commandBuffer, minDepthBounds, maxDepthBounds); 70845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 70855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7086bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetStencilCompareMask(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, 7087bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski uint32_t compareMask) { 708883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 708956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7090b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 70919a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 70925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 709329f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_SETSTENCILREADMASKSTATE, "vkCmdSetStencilCompareMask()"); 70941ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETSTENCILREADMASKSTATE); 70955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->status |= CBSTATUS_STENCIL_READ_MASK_SET; 70965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7097b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7098cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.CmdSetStencilCompareMask(commandBuffer, faceMask, compareMask); 70995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 71005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7101bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetStencilWriteMask(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t writeMask) { 710283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 710356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7104b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 71059a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 71065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 710729f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_SETSTENCILWRITEMASKSTATE, "vkCmdSetStencilWriteMask()"); 71081ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETSTENCILWRITEMASKSTATE); 71095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->status |= CBSTATUS_STENCIL_WRITE_MASK_SET; 71105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7111b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7112cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.CmdSetStencilWriteMask(commandBuffer, faceMask, writeMask); 71135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 71145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7115bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetStencilReference(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t reference) { 711683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 711756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7118b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 71199a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 71205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 712129f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_SETSTENCILREFERENCESTATE, "vkCmdSetStencilReference()"); 71221ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETSTENCILREFERENCESTATE); 71235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->status |= CBSTATUS_STENCIL_REFERENCE_SET; 71245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7125b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7126cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.CmdSetStencilReference(commandBuffer, faceMask, reference); 71275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 71285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7129bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBindDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, 7130bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkPipelineLayout layout, uint32_t firstSet, uint32_t setCount, 7131bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkDescriptorSet *pDescriptorSets, uint32_t dynamicOffsetCount, 7132bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const uint32_t *pDynamicOffsets) { 713383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 713456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7135b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 71369a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 71375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 71385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB->state == CB_RECORDING) { 7139787f29d93dee194c015789cf61c079504c980572Tobin Ehlis // Track total count of dynamic descriptor types to make sure we have an offset for each one 7140787f29d93dee194c015789cf61c079504c980572Tobin Ehlis uint32_t totalDynamicDescriptors = 0; 7141787f29d93dee194c015789cf61c079504c980572Tobin Ehlis string errorString = ""; 7142787f29d93dee194c015789cf61c079504c980572Tobin Ehlis uint32_t lastSetIndex = firstSet + setCount - 1; 7143dd725b03ae4d1296a722d0ec5c9fe63941cabe4bChris Forbes if (lastSetIndex >= pCB->lastBound[pipelineBindPoint].boundDescriptorSets.size()) { 714472d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis pCB->lastBound[pipelineBindPoint].boundDescriptorSets.resize(lastSetIndex + 1); 7145dd725b03ae4d1296a722d0ec5c9fe63941cabe4bChris Forbes pCB->lastBound[pipelineBindPoint].dynamicOffsets.resize(lastSetIndex + 1); 7146dd725b03ae4d1296a722d0ec5c9fe63941cabe4bChris Forbes } 714771511c5a10533c910bfe62c3bcf58e2a4054e7acTobin Ehlis auto oldFinalBoundSet = pCB->lastBound[pipelineBindPoint].boundDescriptorSets[lastSetIndex]; 7148c2a5a36d03bbe52f5854a5884346e4a84115e259Tobin Ehlis auto pipeline_layout = getPipelineLayout(dev_data, layout); 71499784e78683f658f304062235ceb2dd2c2652c357Karl Schultz for (uint32_t set_idx = 0; set_idx < setCount; set_idx++) { 71509a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis cvdescriptorset::DescriptorSet *descriptor_set = GetSetNode(dev_data, pDescriptorSets[set_idx]); 71511c130ea631a82716dc7334de17767536525f2292Tobin Ehlis if (descriptor_set) { 715269b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis pCB->lastBound[pipelineBindPoint].pipeline_layout = *pipeline_layout; 71539784e78683f658f304062235ceb2dd2c2652c357Karl Schultz pCB->lastBound[pipelineBindPoint].boundDescriptorSets[set_idx + firstSet] = descriptor_set; 715483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 71559784e78683f658f304062235ceb2dd2c2652c357Karl Schultz VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t)pDescriptorSets[set_idx], 71569784e78683f658f304062235ceb2dd2c2652c357Karl Schultz __LINE__, DRAWSTATE_NONE, "DS", "Descriptor Set 0x%" PRIxLEAST64 " bound on pipeline %s", 71579784e78683f658f304062235ceb2dd2c2652c357Karl Schultz (uint64_t)pDescriptorSets[set_idx], string_VkPipelineBindPoint(pipelineBindPoint)); 71581c130ea631a82716dc7334de17767536525f2292Tobin Ehlis if (!descriptor_set->IsUpdated() && (descriptor_set->GetTotalDescriptorCount() != 0)) { 715983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, 71609784e78683f658f304062235ceb2dd2c2652c357Karl Schultz VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t)pDescriptorSets[set_idx], 71619784e78683f658f304062235ceb2dd2c2652c357Karl Schultz __LINE__, DRAWSTATE_DESCRIPTOR_SET_NOT_UPDATED, "DS", 7162d79335137b414d5f89284a9ab3e014beb4ada3ebMike Weiblen "Descriptor Set 0x%" PRIxLEAST64 716383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis " bound but it was never updated. You may want to either update it or not bind it.", 71649784e78683f658f304062235ceb2dd2c2652c357Karl Schultz (uint64_t)pDescriptorSets[set_idx]); 7165787f29d93dee194c015789cf61c079504c980572Tobin Ehlis } 7166787f29d93dee194c015789cf61c079504c980572Tobin Ehlis // Verify that set being bound is compatible with overlapping setLayout of pipelineLayout 71679784e78683f658f304062235ceb2dd2c2652c357Karl Schultz if (!verify_set_layout_compatibility(dev_data, descriptor_set, pipeline_layout, set_idx + firstSet, 71689784e78683f658f304062235ceb2dd2c2652c357Karl Schultz errorString)) { 716983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 71709784e78683f658f304062235ceb2dd2c2652c357Karl Schultz VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t)pDescriptorSets[set_idx], 71719784e78683f658f304062235ceb2dd2c2652c357Karl Schultz __LINE__, VALIDATION_ERROR_00974, "DS", 717283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis "descriptorSet #%u being bound is not compatible with overlapping descriptorSetLayout " 717355eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen "at index %u of pipelineLayout 0x%" PRIxLEAST64 " due to: %s. %s", 71749784e78683f658f304062235ceb2dd2c2652c357Karl Schultz set_idx, set_idx + firstSet, reinterpret_cast<uint64_t &>(layout), errorString.c_str(), 717555eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen validation_error_map[VALIDATION_ERROR_00974]); 7176787f29d93dee194c015789cf61c079504c980572Tobin Ehlis } 7177dd725b03ae4d1296a722d0ec5c9fe63941cabe4bChris Forbes 71781c130ea631a82716dc7334de17767536525f2292Tobin Ehlis auto setDynamicDescriptorCount = descriptor_set->GetDynamicDescriptorCount(); 7179dd725b03ae4d1296a722d0ec5c9fe63941cabe4bChris Forbes 71809784e78683f658f304062235ceb2dd2c2652c357Karl Schultz pCB->lastBound[pipelineBindPoint].dynamicOffsets[firstSet + set_idx].clear(); 7181dd725b03ae4d1296a722d0ec5c9fe63941cabe4bChris Forbes 7182dd725b03ae4d1296a722d0ec5c9fe63941cabe4bChris Forbes if (setDynamicDescriptorCount) { 7183787f29d93dee194c015789cf61c079504c980572Tobin Ehlis // First make sure we won't overstep bounds of pDynamicOffsets array 7184dd725b03ae4d1296a722d0ec5c9fe63941cabe4bChris Forbes if ((totalDynamicDescriptors + setDynamicDescriptorCount) > dynamicOffsetCount) { 718583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= 7186787f29d93dee194c015789cf61c079504c980572Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 71879784e78683f658f304062235ceb2dd2c2652c357Karl Schultz VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t)pDescriptorSets[set_idx], 71889784e78683f658f304062235ceb2dd2c2652c357Karl Schultz __LINE__, DRAWSTATE_INVALID_DYNAMIC_OFFSET_COUNT, "DS", 7189414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller "descriptorSet #%u (0x%" PRIxLEAST64 7190787f29d93dee194c015789cf61c079504c980572Tobin Ehlis ") requires %u dynamicOffsets, but only %u dynamicOffsets are left in pDynamicOffsets " 7191787f29d93dee194c015789cf61c079504c980572Tobin Ehlis "array. There must be one dynamic offset for each dynamic descriptor being bound.", 71929784e78683f658f304062235ceb2dd2c2652c357Karl Schultz set_idx, (uint64_t)pDescriptorSets[set_idx], descriptor_set->GetDynamicDescriptorCount(), 7193787f29d93dee194c015789cf61c079504c980572Tobin Ehlis (dynamicOffsetCount - totalDynamicDescriptors)); 7194cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else { // Validate and store dynamic offsets with the set 7195787f29d93dee194c015789cf61c079504c980572Tobin Ehlis // Validate Dynamic Offset Minimums 7196787f29d93dee194c015789cf61c079504c980572Tobin Ehlis uint32_t cur_dyn_offset = totalDynamicDescriptors; 71971c130ea631a82716dc7334de17767536525f2292Tobin Ehlis for (uint32_t d = 0; d < descriptor_set->GetTotalDescriptorCount(); d++) { 71981c130ea631a82716dc7334de17767536525f2292Tobin Ehlis if (descriptor_set->GetTypeFromGlobalIndex(d) == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) { 7199787f29d93dee194c015789cf61c079504c980572Tobin Ehlis if (vk_safe_modulo( 7200787f29d93dee194c015789cf61c079504c980572Tobin Ehlis pDynamicOffsets[cur_dyn_offset], 7201b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis dev_data->phys_dev_properties.properties.limits.minUniformBufferOffsetAlignment) != 0) { 720283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg( 7203787f29d93dee194c015789cf61c079504c980572Tobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 720455eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, VALIDATION_ERROR_00978, 7205cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "DS", 7206cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkCmdBindDescriptorSets(): pDynamicOffsets[%d] is %d but must be a multiple of " 7207cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "device limit minUniformBufferOffsetAlignment 0x%" PRIxLEAST64 ". %s", 7208787f29d93dee194c015789cf61c079504c980572Tobin Ehlis cur_dyn_offset, pDynamicOffsets[cur_dyn_offset], 720955eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen dev_data->phys_dev_properties.properties.limits.minUniformBufferOffsetAlignment, 721055eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen validation_error_map[VALIDATION_ERROR_00978]); 7211787f29d93dee194c015789cf61c079504c980572Tobin Ehlis } 7212787f29d93dee194c015789cf61c079504c980572Tobin Ehlis cur_dyn_offset++; 72131c130ea631a82716dc7334de17767536525f2292Tobin Ehlis } else if (descriptor_set->GetTypeFromGlobalIndex(d) == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) { 7214787f29d93dee194c015789cf61c079504c980572Tobin Ehlis if (vk_safe_modulo( 7215787f29d93dee194c015789cf61c079504c980572Tobin Ehlis pDynamicOffsets[cur_dyn_offset], 7216b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis dev_data->phys_dev_properties.properties.limits.minStorageBufferOffsetAlignment) != 0) { 721783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg( 7218787f29d93dee194c015789cf61c079504c980572Tobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 721955eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, VALIDATION_ERROR_00978, 7220cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "DS", 7221cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkCmdBindDescriptorSets(): pDynamicOffsets[%d] is %d but must be a multiple of " 7222cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "device limit minStorageBufferOffsetAlignment 0x%" PRIxLEAST64 ". %s", 7223787f29d93dee194c015789cf61c079504c980572Tobin Ehlis cur_dyn_offset, pDynamicOffsets[cur_dyn_offset], 722455eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen dev_data->phys_dev_properties.properties.limits.minStorageBufferOffsetAlignment, 722555eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen validation_error_map[VALIDATION_ERROR_00978]); 72265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7227787f29d93dee194c015789cf61c079504c980572Tobin Ehlis cur_dyn_offset++; 72285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 72295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7230dd725b03ae4d1296a722d0ec5c9fe63941cabe4bChris Forbes 72319784e78683f658f304062235ceb2dd2c2652c357Karl Schultz pCB->lastBound[pipelineBindPoint].dynamicOffsets[firstSet + set_idx] = 7232dd725b03ae4d1296a722d0ec5c9fe63941cabe4bChris Forbes std::vector<uint32_t>(pDynamicOffsets + totalDynamicDescriptors, 7233dd725b03ae4d1296a722d0ec5c9fe63941cabe4bChris Forbes pDynamicOffsets + totalDynamicDescriptors + setDynamicDescriptorCount); 7234787f29d93dee194c015789cf61c079504c980572Tobin Ehlis // Keep running total of dynamic descriptor count to verify at the end 7235dd725b03ae4d1296a722d0ec5c9fe63941cabe4bChris Forbes totalDynamicDescriptors += setDynamicDescriptorCount; 72365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 72375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7238787f29d93dee194c015789cf61c079504c980572Tobin Ehlis } else { 72399784e78683f658f304062235ceb2dd2c2652c357Karl Schultz skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 72409784e78683f658f304062235ceb2dd2c2652c357Karl Schultz VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t)pDescriptorSets[set_idx], 72419784e78683f658f304062235ceb2dd2c2652c357Karl Schultz __LINE__, DRAWSTATE_INVALID_SET, "DS", 72429784e78683f658f304062235ceb2dd2c2652c357Karl Schultz "Attempt to bind descriptor set 0x%" PRIxLEAST64 " that doesn't exist!", 72439784e78683f658f304062235ceb2dd2c2652c357Karl Schultz (uint64_t)pDescriptorSets[set_idx]); 72445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 724529f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_BINDDESCRIPTORSETS, "vkCmdBindDescriptorSets()"); 72461ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_BINDDESCRIPTORSETS); 724772d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis // For any previously bound sets, need to set them to "invalid" if they were disturbed by this update 7248cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (firstSet > 0) { // Check set #s below the first bound set 724972d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis for (uint32_t i = 0; i < firstSet; ++i) { 725072d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis if (pCB->lastBound[pipelineBindPoint].boundDescriptorSets[i] && 725171511c5a10533c910bfe62c3bcf58e2a4054e7acTobin Ehlis !verify_set_layout_compatibility(dev_data, pCB->lastBound[pipelineBindPoint].boundDescriptorSets[i], 725269b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis pipeline_layout, i, errorString)) { 725383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg( 725472d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, 725572d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, 725672d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis (uint64_t)pCB->lastBound[pipelineBindPoint].boundDescriptorSets[i], __LINE__, DRAWSTATE_NONE, "DS", 7257d79335137b414d5f89284a9ab3e014beb4ada3ebMike Weiblen "DescriptorSet 0x%" PRIxLEAST64 7258414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller " previously bound as set #%u was disturbed by newly bound pipelineLayout (0x%" PRIxLEAST64 ")", 725972d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis (uint64_t)pCB->lastBound[pipelineBindPoint].boundDescriptorSets[i], i, (uint64_t)layout); 726072d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis pCB->lastBound[pipelineBindPoint].boundDescriptorSets[i] = VK_NULL_HANDLE; 726172d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis } 726272d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis } 726372d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis } 726472d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis // Check if newly last bound set invalidates any remaining bound sets 726572d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis if ((pCB->lastBound[pipelineBindPoint].boundDescriptorSets.size() - 1) > (lastSetIndex)) { 726672d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis if (oldFinalBoundSet && 726769b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis !verify_set_layout_compatibility(dev_data, oldFinalBoundSet, pipeline_layout, lastSetIndex, errorString)) { 726871511c5a10533c910bfe62c3bcf58e2a4054e7acTobin Ehlis auto old_set = oldFinalBoundSet->GetSet(); 726983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= 727072d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, 727171511c5a10533c910bfe62c3bcf58e2a4054e7acTobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, reinterpret_cast<uint64_t &>(old_set), __LINE__, 7272d79335137b414d5f89284a9ab3e014beb4ada3ebMike Weiblen DRAWSTATE_NONE, "DS", "DescriptorSet 0x%" PRIxLEAST64 7273414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller " previously bound as set #%u is incompatible with set 0x%" PRIxLEAST64 727472d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis " newly bound as set #%u so set #%u and any subsequent sets were " 7275414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller "disturbed by newly bound pipelineLayout (0x%" PRIxLEAST64 ")", 727671511c5a10533c910bfe62c3bcf58e2a4054e7acTobin Ehlis reinterpret_cast<uint64_t &>(old_set), lastSetIndex, 727772d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis (uint64_t)pCB->lastBound[pipelineBindPoint].boundDescriptorSets[lastSetIndex], lastSetIndex, 727872d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis lastSetIndex + 1, (uint64_t)layout); 727972d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis pCB->lastBound[pipelineBindPoint].boundDescriptorSets.resize(lastSetIndex + 1); 72805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 72815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 72825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7283787f29d93dee194c015789cf61c079504c980572Tobin Ehlis // dynamicOffsetCount must equal the total number of dynamic descriptors in the sets being bound 7284787f29d93dee194c015789cf61c079504c980572Tobin Ehlis if (totalDynamicDescriptors != dynamicOffsetCount) { 728583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= 728683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 728755eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen (uint64_t)commandBuffer, __LINE__, VALIDATION_ERROR_00975, "DS", 728883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis "Attempting to bind %u descriptorSets with %u dynamic descriptors, but dynamicOffsetCount " 728955eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen "is %u. It should exactly match the number of dynamic descriptors. %s", 729055eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen setCount, totalDynamicDescriptors, dynamicOffsetCount, validation_error_map[VALIDATION_ERROR_00975]); 7291787f29d93dee194c015789cf61c079504c980572Tobin Ehlis } 72925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 729383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= report_error_no_cb_begin(dev_data, commandBuffer, "vkCmdBindDescriptorSets()"); 72945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 72955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7296b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 729783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis if (!skip_call) 72984a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdBindDescriptorSets(commandBuffer, pipelineBindPoint, layout, firstSet, setCount, 72994a0754042cf090e131e9e769d8a3633c228625beChris Forbes pDescriptorSets, dynamicOffsetCount, pDynamicOffsets); 73005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 73015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7302bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBindIndexBuffer(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, 7303bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkIndexType indexType) { 730483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 730556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7306593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis // TODO : Somewhere need to verify that IBs have correct usage state flagged 7307b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7308b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski 73099a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto buffer_state = GetBufferState(dev_data, buffer); 73109a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, commandBuffer); 73115cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis if (cb_node && buffer_state) { 731235ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, buffer_state, "vkCmdBindIndexBuffer()", VALIDATION_ERROR_02543); 7313ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis std::function<bool()> function = [=]() { 73145cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis return ValidateBufferMemoryIsValid(dev_data, buffer_state, "vkCmdBindIndexBuffer()"); 7315ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis }; 73169f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis cb_node->validate_functions.push_back(function); 731729f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, cb_node, CMD_BINDINDEXBUFFER, "vkCmdBindIndexBuffer()"); 73181ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(cb_node, CMD_BINDINDEXBUFFER); 73195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkDeviceSize offset_align = 0; 73205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis switch (indexType) { 7321cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_INDEX_TYPE_UINT16: 7322cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski offset_align = 2; 7323cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 7324cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_INDEX_TYPE_UINT32: 7325cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski offset_align = 4; 7326cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 7327cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 7328cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // ParamChecker should catch bad enum, we'll also throw alignment error below if offset_align stays 0 7329cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 73305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 73315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!offset_align || (offset % offset_align)) { 733283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 733383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis DRAWSTATE_VTX_INDEX_ALIGNMENT_ERROR, "DS", 733483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis "vkCmdBindIndexBuffer() offset (0x%" PRIxLEAST64 ") does not fall on alignment (%s) boundary.", 733583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis offset, string_VkIndexType(indexType)); 73365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 73379f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis cb_node->status |= CBSTATUS_INDEX_BUFFER_BOUND; 7338ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } else { 7339ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis assert(0); 73405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7341b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7342cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.CmdBindIndexBuffer(commandBuffer, buffer, offset, indexType); 73435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 73445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 73455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisvoid updateResourceTracking(GLOBAL_CB_NODE *pCB, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer *pBuffers) { 73465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t end = firstBinding + bindingCount; 73475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB->currentDrawData.buffers.size() < end) { 73485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->currentDrawData.buffers.resize(end); 73495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 73505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < bindingCount; ++i) { 73515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->currentDrawData.buffers[i + firstBinding] = pBuffers[i]; 73525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 73535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 73545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7355e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic inline void updateResourceTrackingOnDraw(GLOBAL_CB_NODE *pCB) { pCB->drawData.push_back(pCB->currentDrawData); } 73565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7357bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBindVertexBuffers(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, 7358bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkBuffer *pBuffers, const VkDeviceSize *pOffsets) { 735983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 736056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7361593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis // TODO : Somewhere need to verify that VBs have correct usage state flagged 7362b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7363b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski 73649a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, commandBuffer); 73659f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis if (cb_node) { 7366593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis for (uint32_t i = 0; i < bindingCount; ++i) { 73679a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto buffer_state = GetBufferState(dev_data, pBuffers[i]); 73685cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis assert(buffer_state); 736935ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, buffer_state, "vkCmdBindVertexBuffers()", VALIDATION_ERROR_02546); 7370ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis std::function<bool()> function = [=]() { 73715cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis return ValidateBufferMemoryIsValid(dev_data, buffer_state, "vkCmdBindVertexBuffers()"); 7372ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis }; 73739f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis cb_node->validate_functions.push_back(function); 73745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 737529f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, cb_node, CMD_BINDVERTEXBUFFER, "vkCmdBindVertexBuffer()"); 73761ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(cb_node, CMD_BINDVERTEXBUFFER); 73779f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis updateResourceTracking(cb_node, firstBinding, bindingCount, pBuffers); 73785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 737983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= report_error_no_cb_begin(dev_data, commandBuffer, "vkCmdBindVertexBuffer()"); 73805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7381b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7382cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.CmdBindVertexBuffers(commandBuffer, firstBinding, bindingCount, pBuffers, pOffsets); 73835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 73845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 738525002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// Expects global_lock to be held by caller 73865569d6457ac22e7d245f3cdee045e71ffbc8b06eTobin Ehlisstatic void MarkStoreImagesAndBuffersAsWritten(layer_data *dev_data, GLOBAL_CB_NODE *pCB) { 73877a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis for (auto imageView : pCB->updateImages) { 73889a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto view_state = GetImageViewState(dev_data, imageView); 7389cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!view_state) continue; 7390249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis 73919a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_state = GetImageState(dev_data, view_state->create_info.image); 73921facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis assert(image_state); 7393e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves std::function<bool()> function = [=]() { 73941facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis SetImageMemoryValid(dev_data, image_state, true); 7395e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves return false; 73967a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis }; 73977a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis pCB->validate_functions.push_back(function); 73987a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis } 73997a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis for (auto buffer : pCB->updateBuffers) { 74009a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto buffer_state = GetBufferState(dev_data, buffer); 74015cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis assert(buffer_state); 7402e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves std::function<bool()> function = [=]() { 74035cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis SetBufferMemoryValid(dev_data, buffer_state, true); 7404e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves return false; 74057a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis }; 74067a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis pCB->validate_functions.push_back(function); 74075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 74085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 74095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7410ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis// Generic function to handle validation for all CmdDraw* type functions 7411ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool ValidateCmdDrawType(layer_data *dev_data, VkCommandBuffer cmd_buffer, bool indexed, VkPipelineBindPoint bind_point, 7412ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis CMD_TYPE cmd_type, GLOBAL_CB_NODE **cb_state, const char *caller, 74134f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes UNIQUE_VALIDATION_ERROR_CODE msg_code, UNIQUE_VALIDATION_ERROR_CODE const dynamic_state_msg_code) { 741458b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis bool skip = false; 74159a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *cb_state = GetCBNode(dev_data, cmd_buffer); 741658b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis if (*cb_state) { 7417ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis skip |= ValidateCmd(dev_data, *cb_state, cmd_type, caller); 74184f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes skip |= ValidateDrawState(dev_data, *cb_state, indexed, bind_point, caller, dynamic_state_msg_code); 741925d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis skip |= (VK_PIPELINE_BIND_POINT_GRAPHICS == bind_point) ? outsideRenderPass(dev_data, *cb_state, caller, msg_code) 742025d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis : insideRenderPass(dev_data, *cb_state, caller, msg_code); 742158b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis } 742258b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis return skip; 742358b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis} 742458b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis 742525d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis// Generic function to handle state update for all CmdDraw* and CmdDispatch* type functions 7426ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void UpdateStateCmdDrawDispatchType(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point, 7427ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis CMD_TYPE cmd_type) { 7428ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis UpdateDrawState(dev_data, cb_state, bind_point); 74292f921d33544c162dcb726fc3c7b915e89c02ff24Tobin Ehlis MarkStoreImagesAndBuffersAsWritten(dev_data, cb_state); 74301ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(cb_state, cmd_type); 743125d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis} 743225d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis 7433ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis// Generic function to handle state update for all CmdDraw* type functions 7434ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void UpdateStateCmdDrawType(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point, 7435ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis CMD_TYPE cmd_type, DRAW_TYPE draw_type) { 7436ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis UpdateStateCmdDrawDispatchType(dev_data, cb_state, bind_point, cmd_type); 7437c0b225e42808ba8fada7a2f67ecd662e376ccf15Tobin Ehlis updateResourceTrackingOnDraw(cb_state); 7438ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis cb_state->drawCount[draw_type]++; 7439ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis} 7440ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis 7441ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool PreCallValidateCmdDraw(layer_data *dev_data, VkCommandBuffer cmd_buffer, bool indexed, VkPipelineBindPoint bind_point, 7442ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis GLOBAL_CB_NODE **cb_state, const char *caller) { 74434f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes return ValidateCmdDrawType(dev_data, cmd_buffer, indexed, bind_point, CMD_DRAW, cb_state, caller, VALIDATION_ERROR_01365, 74444f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes VALIDATION_ERROR_02203); 7445ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis} 7446ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis 7447ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void PostCallRecordCmdDraw(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point) { 7448ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis UpdateStateCmdDrawType(dev_data, cb_state, bind_point, CMD_DRAW, DRAW); 7449c0b225e42808ba8fada7a2f67ecd662e376ccf15Tobin Ehlis} 7450c0b225e42808ba8fada7a2f67ecd662e376ccf15Tobin Ehlis 745189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount, 745289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu uint32_t firstVertex, uint32_t firstInstance) { 745356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 745458b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis GLOBAL_CB_NODE *cb_state = nullptr; 7455b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7456ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis bool skip = PreCallValidateCmdDraw(dev_data, commandBuffer, false, VK_PIPELINE_BIND_POINT_GRAPHICS, &cb_state, "vkCmdDraw()"); 7457b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 745858b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis if (!skip) { 74594a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdDraw(commandBuffer, vertexCount, instanceCount, firstVertex, firstInstance); 7460c0b225e42808ba8fada7a2f67ecd662e376ccf15Tobin Ehlis lock.lock(); 7461ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis PostCallRecordCmdDraw(dev_data, cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS); 7462c0b225e42808ba8fada7a2f67ecd662e376ccf15Tobin Ehlis lock.unlock(); 7463c0b225e42808ba8fada7a2f67ecd662e376ccf15Tobin Ehlis } 74645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 74655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7466ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool PreCallValidateCmdDrawIndexed(layer_data *dev_data, VkCommandBuffer cmd_buffer, bool indexed, 7467ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis VkPipelineBindPoint bind_point, GLOBAL_CB_NODE **cb_state, const char *caller) { 74684f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes return ValidateCmdDrawType(dev_data, cmd_buffer, indexed, bind_point, CMD_DRAWINDEXED, cb_state, caller, VALIDATION_ERROR_01372, 74694f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes VALIDATION_ERROR_02216); 7470ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis} 7471ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis 7472ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void PostCallRecordCmdDrawIndexed(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point) { 7473ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis UpdateStateCmdDrawType(dev_data, cb_state, bind_point, CMD_DRAWINDEXED, DRAW_INDEXED); 7474ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis} 7475ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis 7476bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount, 7477bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance) { 747856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7479ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis GLOBAL_CB_NODE *cb_state = nullptr; 7480b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7481ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis bool skip = PreCallValidateCmdDrawIndexed(dev_data, commandBuffer, true, VK_PIPELINE_BIND_POINT_GRAPHICS, &cb_state, 7482ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis "vkCmdDrawIndexed()"); 7483b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7484ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis if (!skip) { 74854a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdDrawIndexed(commandBuffer, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance); 7486ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis lock.lock(); 7487ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis PostCallRecordCmdDrawIndexed(dev_data, cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS); 7488ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis lock.unlock(); 7489ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis } 74905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 74915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7492ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool PreCallValidateCmdDrawIndirect(layer_data *dev_data, VkCommandBuffer cmd_buffer, VkBuffer buffer, bool indexed, 7493ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis VkPipelineBindPoint bind_point, GLOBAL_CB_NODE **cb_state, BUFFER_STATE **buffer_state, 7494ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis const char *caller) { 74954f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes bool skip = ValidateCmdDrawType(dev_data, cmd_buffer, indexed, bind_point, CMD_DRAWINDIRECT, cb_state, caller, 74964f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes VALIDATION_ERROR_01381, VALIDATION_ERROR_02234); 74979a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *buffer_state = GetBufferState(dev_data, buffer); 749835ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis skip |= ValidateMemoryIsBoundToBuffer(dev_data, *buffer_state, caller, VALIDATION_ERROR_02544); 7499d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis return skip; 7500d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis} 7501d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis 7502ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void PostCallRecordCmdDrawIndirect(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point, 7503ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis BUFFER_STATE *buffer_state) { 7504ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis UpdateStateCmdDrawType(dev_data, cb_state, bind_point, CMD_DRAWINDIRECT, DRAW_INDIRECT); 7505d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis AddCommandBufferBindingBuffer(dev_data, cb_state, buffer_state); 7506d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis} 7507d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis 7508bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count, 7509bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski uint32_t stride) { 751056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7511d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis GLOBAL_CB_NODE *cb_state = nullptr; 7512d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis BUFFER_STATE *buffer_state = nullptr; 7513b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7514872a2f0ca3ffdeddfa7483e777191fa64b853892Tony Barbour bool skip = PreCallValidateCmdDrawIndirect(dev_data, commandBuffer, buffer, false, VK_PIPELINE_BIND_POINT_GRAPHICS, &cb_state, 7515ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis &buffer_state, "vkCmdDrawIndirect()"); 7516b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7517d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis if (!skip) { 75184a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdDrawIndirect(commandBuffer, buffer, offset, count, stride); 7519d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis lock.lock(); 7520ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis PostCallRecordCmdDrawIndirect(dev_data, cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, buffer_state); 7521d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis lock.unlock(); 7522d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis } 75235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 75245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7525ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool PreCallValidateCmdDrawIndexedIndirect(layer_data *dev_data, VkCommandBuffer cmd_buffer, VkBuffer buffer, bool indexed, 7526ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis VkPipelineBindPoint bind_point, GLOBAL_CB_NODE **cb_state, 7527ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis BUFFER_STATE **buffer_state, const char *caller) { 7528ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis bool skip = ValidateCmdDrawType(dev_data, cmd_buffer, indexed, bind_point, CMD_DRAWINDEXEDINDIRECT, cb_state, caller, 75294f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes VALIDATION_ERROR_01393, VALIDATION_ERROR_02272); 75309a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *buffer_state = GetBufferState(dev_data, buffer); 753135ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis skip |= ValidateMemoryIsBoundToBuffer(dev_data, *buffer_state, caller, VALIDATION_ERROR_02545); 75320c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis return skip; 75330c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis} 75340c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis 7535ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void PostCallRecordCmdDrawIndexedIndirect(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point, 7536ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis BUFFER_STATE *buffer_state) { 7537ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis UpdateStateCmdDrawType(dev_data, cb_state, bind_point, CMD_DRAWINDEXEDINDIRECT, DRAW_INDEXED_INDIRECT); 75380c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis AddCommandBufferBindingBuffer(dev_data, cb_state, buffer_state); 75390c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis} 75400c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis 7541bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, 7542bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski uint32_t count, uint32_t stride) { 754356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 75440c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis GLOBAL_CB_NODE *cb_state = nullptr; 75450c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis BUFFER_STATE *buffer_state = nullptr; 7546b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 75470c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis bool skip = PreCallValidateCmdDrawIndexedIndirect(dev_data, commandBuffer, buffer, true, VK_PIPELINE_BIND_POINT_GRAPHICS, 7548ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis &cb_state, &buffer_state, "vkCmdDrawIndexedIndirect()"); 7549b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 75500c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis if (!skip) { 75514a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdDrawIndexedIndirect(commandBuffer, buffer, offset, count, stride); 75520c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis lock.lock(); 7553ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis PostCallRecordCmdDrawIndexedIndirect(dev_data, cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, buffer_state); 75540c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis lock.unlock(); 75550c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis } 75565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 75575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7558ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool PreCallValidateCmdDispatch(layer_data *dev_data, VkCommandBuffer cmd_buffer, bool indexed, 7559ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis VkPipelineBindPoint bind_point, GLOBAL_CB_NODE **cb_state, const char *caller) { 75604f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes return ValidateCmdDrawType(dev_data, cmd_buffer, indexed, bind_point, CMD_DISPATCH, cb_state, caller, VALIDATION_ERROR_01562, 75614f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes VALIDATION_ERROR_UNDEFINED); 756225d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis} 756325d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis 7564ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void PostCallRecordCmdDispatch(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point) { 7565ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis UpdateStateCmdDrawDispatchType(dev_data, cb_state, bind_point, CMD_DISPATCH); 756625d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis} 756725d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis 756889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z) { 756956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 757025d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis GLOBAL_CB_NODE *cb_state = nullptr; 7571b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7572ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis bool skip = 7573ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis PreCallValidateCmdDispatch(dev_data, commandBuffer, false, VK_PIPELINE_BIND_POINT_COMPUTE, &cb_state, "vkCmdDispatch()"); 7574b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 757525d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis if (!skip) { 75764a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdDispatch(commandBuffer, x, y, z); 757725d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis lock.lock(); 7578ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis PostCallRecordCmdDispatch(dev_data, cb_state, VK_PIPELINE_BIND_POINT_COMPUTE); 757925d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis lock.unlock(); 758025d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis } 75815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 75825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7583ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool PreCallValidateCmdDispatchIndirect(layer_data *dev_data, VkCommandBuffer cmd_buffer, VkBuffer buffer, bool indexed, 7584ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis VkPipelineBindPoint bind_point, GLOBAL_CB_NODE **cb_state, 7585ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis BUFFER_STATE **buffer_state, const char *caller) { 7586ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis bool skip = ValidateCmdDrawType(dev_data, cmd_buffer, indexed, bind_point, CMD_DISPATCHINDIRECT, cb_state, caller, 75874f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes VALIDATION_ERROR_01569, VALIDATION_ERROR_UNDEFINED); 75889a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *buffer_state = GetBufferState(dev_data, buffer); 758935ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis skip |= ValidateMemoryIsBoundToBuffer(dev_data, *buffer_state, caller, VALIDATION_ERROR_02547); 759079c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis return skip; 759179c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis} 759279c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis 7593ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void PostCallRecordCmdDispatchIndirect(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point, 7594ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis BUFFER_STATE *buffer_state) { 7595ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis UpdateStateCmdDrawDispatchType(dev_data, cb_state, bind_point, CMD_DISPATCHINDIRECT); 759679c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis AddCommandBufferBindingBuffer(dev_data, cb_state, buffer_state); 759779c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis} 759879c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis 7599bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset) { 760056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 760179c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis GLOBAL_CB_NODE *cb_state = nullptr; 760279c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis BUFFER_STATE *buffer_state = nullptr; 7603b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 76047433ab60c7ff16d37edb0f8b17b606ccd363e210Tobin Ehlis bool skip = PreCallValidateCmdDispatchIndirect(dev_data, commandBuffer, buffer, false, VK_PIPELINE_BIND_POINT_COMPUTE, 7605ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis &cb_state, &buffer_state, "vkCmdDispatchIndirect()"); 7606b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 760779c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis if (!skip) { 76084a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdDispatchIndirect(commandBuffer, buffer, offset); 760979c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis lock.lock(); 7610ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis PostCallRecordCmdDispatchIndirect(dev_data, cb_state, VK_PIPELINE_BIND_POINT_COMPUTE, buffer_state); 761179c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis lock.unlock(); 761279c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis } 76135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 76145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 761589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdCopyBuffer(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer, 761689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu uint32_t regionCount, const VkBufferCopy *pRegions) { 7617c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7618b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7619ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis 7620c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski auto cb_node = GetCBNode(device_data, commandBuffer); 7621c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski auto src_buffer_state = GetBufferState(device_data, srcBuffer); 7622c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski auto dst_buffer_state = GetBufferState(device_data, dstBuffer); 7623593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 7624c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski if (cb_node && src_buffer_state && dst_buffer_state) { 7625c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski bool skip = PreCallValidateCmdCopyBuffer(device_data, cb_node, src_buffer_state, dst_buffer_state); 7626c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski if (!skip) { 7627c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski PreCallRecordCmdCopyBuffer(device_data, cb_node, src_buffer_state, dst_buffer_state); 7628c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski lock.unlock(); 7629c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski device_data->dispatch_table.CmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, regionCount, pRegions); 7630c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski } 7631ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } else { 7632c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski lock.unlock(); 7633ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis assert(0); 76345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 76355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 76365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7637bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdCopyImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, 7638bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, 7639bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkImageCopy *pRegions) { 76406a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski bool skip = false; 76416a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7642b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7643249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis 76446a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski auto cb_node = GetCBNode(device_data, commandBuffer); 76456a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski auto src_image_state = GetImageState(device_data, srcImage); 76466a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski auto dst_image_state = GetImageState(device_data, dstImage); 76471facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis if (cb_node && src_image_state && dst_image_state) { 76486a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski skip = PreCallValidateCmdCopyImage(device_data, cb_node, src_image_state, dst_image_state, regionCount, pRegions, 76496a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski srcImageLayout, dstImageLayout); 76506a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski if (!skip) { 76516a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski PreCallRecordCmdCopyImage(device_data, cb_node, src_image_state, dst_image_state); 76526a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski lock.unlock(); 76536a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski device_data->dispatch_table.CmdCopyImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, 76546a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski pRegions); 76555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7656249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis } else { 76576a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski lock.unlock(); 7658249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis assert(0); 76595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 76605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 76615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7662eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski// Validate that an image's sampleCount matches the requirement for a specific API call 766360568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinskibool ValidateImageSampleCount(layer_data *dev_data, IMAGE_STATE *image_state, VkSampleCountFlagBits sample_count, 766460568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski const char *location, UNIQUE_VALIDATION_ERROR_CODE msgCode) { 7665eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski bool skip = false; 76661facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis if (image_state->createInfo.samples != sample_count) { 766755eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen skip = 766855eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 766955eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen reinterpret_cast<uint64_t &>(image_state->image), 0, msgCode, "DS", 767055eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen "%s for image 0x%" PRIxLEAST64 " was created with a sample count of %s but must be %s. %s", location, 767155eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen reinterpret_cast<uint64_t &>(image_state->image), string_VkSampleCountFlagBits(image_state->createInfo.samples), 767255eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen string_VkSampleCountFlagBits(sample_count), validation_error_map[msgCode]); 7673eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski } 7674eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski return skip; 7675eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski} 7676eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski 7677bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBlitImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, 7678bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, 7679bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkImageBlit *pRegions, VkFilter filter) { 768056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7681b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7682593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 76839a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, commandBuffer); 76849a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto src_image_state = GetImageState(dev_data, srcImage); 76859a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto dst_image_state = GetImageState(dev_data, dstImage); 76860dc51740dbd7b9f0ba7c071e0bf96f63d6d48c85Mark Lobodzinski 7687055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski bool skip = PreCallValidateCmdBlitImage(dev_data, cb_node, src_image_state, dst_image_state, regionCount, pRegions, filter); 76880dc51740dbd7b9f0ba7c071e0bf96f63d6d48c85Mark Lobodzinski 7689dca02371c9531e7a9a2a51decae1db4d297862c4Mark Lobodzinski if (!skip) { 7690eebd811afd800663f15fda8fc71bc203a03fe294Mark Lobodzinski PreCallRecordCmdBlitImage(dev_data, cb_node, src_image_state, dst_image_state); 7691eebd811afd800663f15fda8fc71bc203a03fe294Mark Lobodzinski lock.unlock(); 76924a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdBlitImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, 76934a0754042cf090e131e9e769d8a3633c228625beChris Forbes pRegions, filter); 76940dc51740dbd7b9f0ba7c071e0bf96f63d6d48c85Mark Lobodzinski } 76955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 76965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7697bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdCopyBufferToImage(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage, 7698bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkImageLayout dstImageLayout, uint32_t regionCount, 7699bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkBufferImageCopy *pRegions) { 770083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 770156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7702b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7703593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 77049a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, commandBuffer); 77059a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto src_buff_state = GetBufferState(dev_data, srcBuffer); 77069a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto dst_image_state = GetImageState(dev_data, dstImage); 77075cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis if (cb_node && src_buff_state && dst_image_state) { 770855eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen skip_call |= ValidateImageSampleCount(dev_data, dst_image_state, VK_SAMPLE_COUNT_1_BIT, 770955eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen "vkCmdCopyBufferToImage(): dstImage", VALIDATION_ERROR_01232); 771035ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, src_buff_state, "vkCmdCopyBufferToImage()", VALIDATION_ERROR_02535); 771135ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis skip_call |= ValidateMemoryIsBoundToImage(dev_data, dst_image_state, "vkCmdCopyBufferToImage()", VALIDATION_ERROR_02536); 77125cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis AddCommandBufferBindingBuffer(dev_data, cb_node, src_buff_state); 77131facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis AddCommandBufferBindingImage(dev_data, cb_node, dst_image_state); 77141b8a6bd9260c52ca6c6cfe1e34f142f93e1e2cc6Jeremy Hayes skip_call |= 77155cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis ValidateBufferUsageFlags(dev_data, src_buff_state, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, true, VALIDATION_ERROR_01230, 77161b8a6bd9260c52ca6c6cfe1e34f142f93e1e2cc6Jeremy Hayes "vkCmdCopyBufferToImage()", "VK_BUFFER_USAGE_TRANSFER_SRC_BIT"); 77171facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis skip_call |= ValidateImageUsageFlags(dev_data, dst_image_state, VK_IMAGE_USAGE_TRANSFER_DST_BIT, true, 77181b8a6bd9260c52ca6c6cfe1e34f142f93e1e2cc6Jeremy Hayes VALIDATION_ERROR_01231, "vkCmdCopyBufferToImage()", "VK_IMAGE_USAGE_TRANSFER_DST_BIT"); 7719e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves std::function<bool()> function = [=]() { 77201facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis SetImageMemoryValid(dev_data, dst_image_state, true); 7721e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves return false; 77225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis }; 77239f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis cb_node->validate_functions.push_back(function); 77245cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis function = [=]() { return ValidateBufferMemoryIsValid(dev_data, src_buff_state, "vkCmdCopyBufferToImage()"); }; 77259f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis cb_node->validate_functions.push_back(function); 7726593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 772729f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, cb_node, CMD_COPYBUFFERTOIMAGE, "vkCmdCopyBufferToImage()"); 77281ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(cb_node, CMD_COPYBUFFERTOIMAGE); 7729ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen skip_call |= insideRenderPass(dev_data, cb_node, "vkCmdCopyBufferToImage()", VALIDATION_ERROR_01242); 77305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < regionCount; ++i) { 773155eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen skip_call |= VerifyDestImageLayout(dev_data, cb_node, dstImage, pRegions[i].imageSubresource, dstImageLayout, 773255eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen VALIDATION_ERROR_01234); 77331facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis skip_call |= ValidateCopyBufferImageTransferGranularityRequirements(dev_data, cb_node, dst_image_state, &pRegions[i], i, 77349ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano "vkCmdCopyBufferToImage()"); 77355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7736ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } else { 7737ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis assert(0); 77385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7739b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 774083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis if (!skip_call) 77414a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdCopyBufferToImage(commandBuffer, srcBuffer, dstImage, dstImageLayout, regionCount, pRegions); 77425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 77435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7744bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdCopyImageToBuffer(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, 7745bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkBuffer dstBuffer, uint32_t regionCount, const VkBufferImageCopy *pRegions) { 774683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 774756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7748b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7749593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 77509a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, commandBuffer); 77519a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto src_image_state = GetImageState(dev_data, srcImage); 77529a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto dst_buff_state = GetBufferState(dev_data, dstBuffer); 77535cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis if (cb_node && src_image_state && dst_buff_state) { 775455eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen skip_call |= ValidateImageSampleCount(dev_data, src_image_state, VK_SAMPLE_COUNT_1_BIT, 775555eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen "vkCmdCopyImageToBuffer(): srcImage", VALIDATION_ERROR_01249); 775635ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis skip_call |= ValidateMemoryIsBoundToImage(dev_data, src_image_state, "vkCmdCopyImageToBuffer()", VALIDATION_ERROR_02537); 775735ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, dst_buff_state, "vkCmdCopyImageToBuffer()", VALIDATION_ERROR_02538); 7758249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis // Update bindings between buffer/image and cmd buffer 77591facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis AddCommandBufferBindingImage(dev_data, cb_node, src_image_state); 77605cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis AddCommandBufferBindingBuffer(dev_data, cb_node, dst_buff_state); 7761249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis // Validate that SRC image & DST buffer have correct usage flags set 77621facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis skip_call |= ValidateImageUsageFlags(dev_data, src_image_state, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, true, 77631b8a6bd9260c52ca6c6cfe1e34f142f93e1e2cc6Jeremy Hayes VALIDATION_ERROR_01248, "vkCmdCopyImageToBuffer()", "VK_IMAGE_USAGE_TRANSFER_SRC_BIT"); 77641b8a6bd9260c52ca6c6cfe1e34f142f93e1e2cc6Jeremy Hayes skip_call |= 77655cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis ValidateBufferUsageFlags(dev_data, dst_buff_state, VK_BUFFER_USAGE_TRANSFER_DST_BIT, true, VALIDATION_ERROR_01252, 77661b8a6bd9260c52ca6c6cfe1e34f142f93e1e2cc6Jeremy Hayes "vkCmdCopyImageToBuffer()", "VK_BUFFER_USAGE_TRANSFER_DST_BIT"); 7767e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves std::function<bool()> function = [=]() { 77681facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis return ValidateImageMemoryIsValid(dev_data, src_image_state, "vkCmdCopyImageToBuffer()"); 7769e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves }; 77709f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis cb_node->validate_functions.push_back(function); 7771593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis function = [=]() { 77725cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis SetBufferMemoryValid(dev_data, dst_buff_state, true); 7773e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves return false; 77745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis }; 77759f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis cb_node->validate_functions.push_back(function); 7776593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 777729f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, cb_node, CMD_COPYIMAGETOBUFFER, "vkCmdCopyImageToBuffer()"); 77781ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(cb_node, CMD_COPYIMAGETOBUFFER); 7779ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen skip_call |= insideRenderPass(dev_data, cb_node, "vkCmdCopyImageToBuffer()", VALIDATION_ERROR_01260); 77805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < regionCount; ++i) { 778155eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen skip_call |= VerifySourceImageLayout(dev_data, cb_node, srcImage, pRegions[i].imageSubresource, srcImageLayout, 778255eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen VALIDATION_ERROR_01251); 77831facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis skip_call |= ValidateCopyBufferImageTransferGranularityRequirements(dev_data, cb_node, src_image_state, &pRegions[i], i, 77849ecb1daf727b16dfa6a26236bd93cd75f4d12696Gregory Mitrano "CmdCopyImageToBuffer"); 77855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7786ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } else { 7787ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis assert(0); 77885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7789b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 779083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis if (!skip_call) 77914a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdCopyImageToBuffer(commandBuffer, srcImage, srcImageLayout, dstBuffer, regionCount, pRegions); 77925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 77935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7794bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdUpdateBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, 7795bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDeviceSize dataSize, const uint32_t *pData) { 779683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 779756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7798b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7799593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 78009a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, commandBuffer); 78019a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto dst_buff_state = GetBufferState(dev_data, dstBuffer); 78025cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis if (cb_node && dst_buff_state) { 780335ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, dst_buff_state, "vkCmdUpdateBuffer()", VALIDATION_ERROR_02530); 7804ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis // Update bindings between buffer and cmd buffer 78055cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis AddCommandBufferBindingBuffer(dev_data, cb_node, dst_buff_state); 7806ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis // Validate that DST buffer has correct usage flags set 78075cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis skip_call |= ValidateBufferUsageFlags(dev_data, dst_buff_state, VK_BUFFER_USAGE_TRANSFER_DST_BIT, true, 78081b8a6bd9260c52ca6c6cfe1e34f142f93e1e2cc6Jeremy Hayes VALIDATION_ERROR_01146, "vkCmdUpdateBuffer()", "VK_BUFFER_USAGE_TRANSFER_DST_BIT"); 7809e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves std::function<bool()> function = [=]() { 78105cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis SetBufferMemoryValid(dev_data, dst_buff_state, true); 7811e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves return false; 78125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis }; 78139f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis cb_node->validate_functions.push_back(function); 7814593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 781529f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, cb_node, CMD_UPDATEBUFFER, "vkCmdUpdateBuffer()"); 78161ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(cb_node, CMD_UPDATEBUFFER); 7817ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen skip_call |= insideRenderPass(dev_data, cb_node, "vkCmdUpdateBuffer()", VALIDATION_ERROR_01155); 7818ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } else { 7819ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis assert(0); 78205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7821b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7822cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.CmdUpdateBuffer(commandBuffer, dstBuffer, dstOffset, dataSize, pData); 78235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 78245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7825bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdFillBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, 7826bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDeviceSize size, uint32_t data) { 782723bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7828b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 782923bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski auto cb_node = GetCBNode(device_data, commandBuffer); 783023bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski auto buffer_state = GetBufferState(device_data, dstBuffer); 7831593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 783223bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski if (cb_node && buffer_state) { 783323bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski bool skip = PreCallValidateCmdFillBuffer(device_data, cb_node, buffer_state); 783423bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski if (!skip) { 783523bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski PreCallRecordCmdFillBuffer(device_data, cb_node, buffer_state); 783623bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski lock.unlock(); 783723bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski device_data->dispatch_table.CmdFillBuffer(commandBuffer, dstBuffer, dstOffset, size, data); 783823bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski } 7839ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } else { 784023bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski lock.unlock(); 7841ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis assert(0); 78425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 78435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 78445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 78454028af23e688ab5730f48ab2244dd042e2eefaedMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdClearAttachments(VkCommandBuffer commandBuffer, uint32_t attachmentCount, 78464028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski const VkClearAttachment *pAttachments, uint32_t rectCount, 78474028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski const VkClearRect *pRects) { 78484028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski bool skip = false; 784956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 78504028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski { 78514028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski std::lock_guard<std::mutex> lock(global_lock); 78524028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski skip = PreCallValidateCmdClearAttachments(dev_data, commandBuffer, attachmentCount, pAttachments, rectCount, pRects); 78534028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski } 7854cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdClearAttachments(commandBuffer, attachmentCount, pAttachments, rectCount, pRects); 78555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 78565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 78570482c55760707900fcd072f6895c121bcf055f6eMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdClearColorImage(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, 78580482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski const VkClearColorValue *pColor, uint32_t rangeCount, 78590482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski const VkImageSubresourceRange *pRanges) { 786056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7861b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 78620482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski 78630482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski bool skip = PreCallValidateCmdClearColorImage(dev_data, commandBuffer, image, imageLayout, rangeCount, pRanges); 78640482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski if (!skip) { 78650482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski PreCallRecordCmdClearImage(dev_data, commandBuffer, image, imageLayout, rangeCount, pRanges, CMD_CLEARCOLORIMAGE); 78660482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski lock.unlock(); 78670482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski dev_data->dispatch_table.CmdClearColorImage(commandBuffer, image, imageLayout, pColor, rangeCount, pRanges); 78680482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski } 78690482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski} 78700482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski 78710482c55760707900fcd072f6895c121bcf055f6eMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdClearDepthStencilImage(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, 78720482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski const VkClearDepthStencilValue *pDepthStencil, uint32_t rangeCount, 78730482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski const VkImageSubresourceRange *pRanges) { 787456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 78750482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski std::unique_lock<std::mutex> lock(global_lock); 78760482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski 78770482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski bool skip = PreCallValidateCmdClearDepthStencilImage(dev_data, commandBuffer, image, imageLayout, rangeCount, pRanges); 78780482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski if (!skip) { 78790482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski PreCallRecordCmdClearImage(dev_data, commandBuffer, image, imageLayout, rangeCount, pRanges, CMD_CLEARDEPTHSTENCILIMAGE); 78800482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski lock.unlock(); 78810482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski dev_data->dispatch_table.CmdClearDepthStencilImage(commandBuffer, image, imageLayout, pDepthStencil, rangeCount, pRanges); 78827f8aa8f5abceedbb599ef69af1dfbb38c0df2660Slawomir Cygan } 78835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 78845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7885bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdResolveImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, 7886bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, 7887bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkImageResolve *pRegions) { 788856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7889b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7890593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 78919a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, commandBuffer); 78929a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto src_image_state = GetImageState(dev_data, srcImage); 78939a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto dst_image_state = GetImageState(dev_data, dstImage); 789409fe5ac5edaec7f0dbcc9fd696e68194569aea89Mark Lobodzinski 789525f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski bool skip = PreCallValidateCmdResolveImage(dev_data, cb_node, src_image_state, dst_image_state, regionCount, pRegions); 789609fe5ac5edaec7f0dbcc9fd696e68194569aea89Mark Lobodzinski 789709fe5ac5edaec7f0dbcc9fd696e68194569aea89Mark Lobodzinski if (!skip) { 78986c0400e625554ce7fddb833eeace0de19cfcc965Mark Lobodzinski PreCallRecordCmdResolveImage(dev_data, cb_node, src_image_state, dst_image_state); 78996c0400e625554ce7fddb833eeace0de19cfcc965Mark Lobodzinski lock.unlock(); 79004a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdResolveImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, 79014a0754042cf090e131e9e769d8a3633c228625beChris Forbes pRegions); 790209fe5ac5edaec7f0dbcc9fd696e68194569aea89Mark Lobodzinski } 79035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 79045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7905b06379a335598a3d8c53c694e875dda19eeab612Mark LobodzinskiVKAPI_ATTR void VKAPI_CALL GetImageSubresourceLayout(VkDevice device, VkImage image, const VkImageSubresource *pSubresource, 7906b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski VkSubresourceLayout *pLayout) { 7907b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski bool skipCall = false; 790856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *device_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 7909b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski VkFormat format; 7910b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski 79119a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto imageEntry = GetImageState(device_data, image); 7912b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski 7913b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski // Validate that image aspects match formats 7914b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski if (imageEntry) { 7915b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski format = imageEntry->createInfo.format; 7916b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski if (vk_format_is_color(format)) { 7917b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski if (pSubresource->aspectMask != VK_IMAGE_ASPECT_COLOR_BIT) { 7918b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski std::stringstream ss; 7919b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski ss << "vkGetImageSubresourceLayout: For color formats, the aspectMask field of VkImageSubresource must be " 7920b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski "VK_IMAGE_ASPECT_COLOR."; 7921b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 7922b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski (uint64_t)image, __LINE__, VALIDATION_ERROR_00741, "IMAGE", "%s. %s", ss.str().c_str(), 7923b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski validation_error_map[VALIDATION_ERROR_00741]); 7924b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski } 7925b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski } else if (vk_format_is_depth_or_stencil(format)) { 7926b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski if ((pSubresource->aspectMask != VK_IMAGE_ASPECT_DEPTH_BIT) && 7927b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski (pSubresource->aspectMask != VK_IMAGE_ASPECT_STENCIL_BIT)) { 7928b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski std::stringstream ss; 7929b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski ss << "vkGetImageSubresourceLayout: For depth/stencil formats, the aspectMask selects either the depth or stencil " 7930b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski "image aspectMask."; 7931b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 7932b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski (uint64_t)image, __LINE__, VALIDATION_ERROR_00741, "IMAGE", "%s. %s", ss.str().c_str(), 7933b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski validation_error_map[VALIDATION_ERROR_00741]); 7934b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski } 7935b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski } 7936b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski } 7937b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski 7938b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski if (!skipCall) { 7939b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski device_data->dispatch_table.GetImageSubresourceLayout(device, image, pSubresource, pLayout); 7940b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski } 7941b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski} 7942b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski 7943b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentinebool setEventStageMask(VkQueue queue, VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) { 794456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 79459a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 7946b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine if (pCB) { 7947b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine pCB->eventToStageMap[event] = stageMask; 7948b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine } 7949b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine auto queue_data = dev_data->queueMap.find(queue); 7950b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine if (queue_data != dev_data->queueMap.end()) { 7951b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine queue_data->second.eventToStageMap[event] = stageMask; 7952b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine } 7953b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine return false; 7954b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine} 7955b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine 7956bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) { 795783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 795856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7959b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 79609a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 79615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 796229f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_SETEVENT, "vkCmdSetEvent()"); 79631ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETEVENT); 7964ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen skip_call |= insideRenderPass(dev_data, pCB, "vkCmdSetEvent()", VALIDATION_ERROR_00238); 7965208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis skip_call |= 7966208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis ValidateStageMaskGsTsEnables(dev_data, stageMask, "vkCmdSetEvent()", VALIDATION_ERROR_00230, VALIDATION_ERROR_00231); 79679a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto event_state = GetEventNode(dev_data, event); 79684710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis if (event_state) { 79694710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis addCommandBufferBinding(&event_state->cb_bindings, 7970ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis {reinterpret_cast<uint64_t &>(event), VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT}, pCB); 79714710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis event_state->cb_bindings.insert(pCB); 7972ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis } 79735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->events.push_back(event); 7974c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine if (!pCB->waitedEvents.count(event)) { 7975c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine pCB->writeEventsBeforeWait.push_back(event); 7976c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine } 7977b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine std::function<bool(VkQueue)> eventUpdate = 7978b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine std::bind(setEventStageMask, std::placeholders::_1, commandBuffer, event, stageMask); 7979b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine pCB->eventUpdates.push_back(eventUpdate); 79805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7981b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7982cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.CmdSetEvent(commandBuffer, event, stageMask); 79835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 79845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7985bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdResetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) { 798683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 798756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7988b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 79899a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 79905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 799129f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_RESETEVENT, "vkCmdResetEvent()"); 79921ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_RESETEVENT); 7993ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen skip_call |= insideRenderPass(dev_data, pCB, "vkCmdResetEvent()", VALIDATION_ERROR_00249); 7994208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis skip_call |= 7995208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis ValidateStageMaskGsTsEnables(dev_data, stageMask, "vkCmdResetEvent()", VALIDATION_ERROR_00240, VALIDATION_ERROR_00241); 79969a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto event_state = GetEventNode(dev_data, event); 79974710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis if (event_state) { 79984710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis addCommandBufferBinding(&event_state->cb_bindings, 7999ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis {reinterpret_cast<uint64_t &>(event), VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT}, pCB); 80004710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis event_state->cb_bindings.insert(pCB); 8001ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis } 80025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->events.push_back(event); 8003c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine if (!pCB->waitedEvents.count(event)) { 8004c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine pCB->writeEventsBeforeWait.push_back(event); 8005c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine } 8006208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis // TODO : Add check for VALIDATION_ERROR_00226 8007b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine std::function<bool(VkQueue)> eventUpdate = 8008b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine std::bind(setEventStageMask, std::placeholders::_1, commandBuffer, event, VkPipelineStageFlags(0)); 8009b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine pCB->eventUpdates.push_back(eventUpdate); 80105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8011b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 8012cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.CmdResetEvent(commandBuffer, event, stageMask); 80135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 80145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8015e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool ValidateBarriers(const char *funcName, VkCommandBuffer cmdBuffer, uint32_t memBarrierCount, 8016e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves const VkMemoryBarrier *pMemBarriers, uint32_t bufferBarrierCount, 8017e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves const VkBufferMemoryBarrier *pBufferMemBarriers, uint32_t imageMemBarrierCount, 8018e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves const VkImageMemoryBarrier *pImageMemBarriers) { 8019a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis bool skip = false; 802056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(cmdBuffer), layer_data_map); 80219a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, cmdBuffer); 80225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB->activeRenderPass && memBarrierCount) { 8023ee691f5c5fa87aac3750454d2bca2cb582e4e817Chris Forbes if (!pCB->activeRenderPass->hasSelfDependency[pCB->activeSubpass]) { 8024a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 8025cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski DRAWSTATE_INVALID_BARRIER, "DS", 8026cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s: Barriers cannot be set during subpass %d " 8027cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "with no self dependency specified.", 8028a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis funcName, pCB->activeSubpass); 80295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 80305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 80315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < imageMemBarrierCount; ++i) { 80325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto mem_barrier = &pImageMemBarriers[i]; 80339a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_data = GetImageState(dev_data, mem_barrier->image); 80346d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis if (image_data) { 80355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t src_q_f_index = mem_barrier->srcQueueFamilyIndex; 80365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t dst_q_f_index = mem_barrier->dstQueueFamilyIndex; 80376d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis if (image_data->createInfo.sharingMode == VK_SHARING_MODE_CONCURRENT) { 80385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // srcQueueFamilyIndex and dstQueueFamilyIndex must both 80395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // be VK_QUEUE_FAMILY_IGNORED 80405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if ((src_q_f_index != VK_QUEUE_FAMILY_IGNORED) || (dst_q_f_index != VK_QUEUE_FAMILY_IGNORED)) { 8041cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski skip |= 8042cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 8043cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski DRAWSTATE_INVALID_QUEUE_INDEX, "DS", "%s: Image Barrier for image 0x%" PRIx64 8044cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " was created with sharingMode of " 8045cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "VK_SHARING_MODE_CONCURRENT. Src and dst " 8046cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "queueFamilyIndices must be VK_QUEUE_FAMILY_IGNORED.", 8047cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski funcName, reinterpret_cast<const uint64_t &>(mem_barrier->image)); 80485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 80495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 80505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Sharing mode is VK_SHARING_MODE_EXCLUSIVE. srcQueueFamilyIndex and 80515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // dstQueueFamilyIndex must either both be VK_QUEUE_FAMILY_IGNORED, 80525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // or both be a valid queue family 80535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (((src_q_f_index == VK_QUEUE_FAMILY_IGNORED) || (dst_q_f_index == VK_QUEUE_FAMILY_IGNORED)) && 80545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (src_q_f_index != dst_q_f_index)) { 8055a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis skip |= 80565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 8057cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski DRAWSTATE_INVALID_QUEUE_INDEX, "DS", "%s: Image 0x%" PRIx64 8058cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " was created with sharingMode " 80595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis "of VK_SHARING_MODE_EXCLUSIVE. If one of src- or " 80605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis "dstQueueFamilyIndex is VK_QUEUE_FAMILY_IGNORED, both " 80615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis "must be.", 80625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis funcName, reinterpret_cast<const uint64_t &>(mem_barrier->image)); 80635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (((src_q_f_index != VK_QUEUE_FAMILY_IGNORED) && (dst_q_f_index != VK_QUEUE_FAMILY_IGNORED)) && 8064b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis ((src_q_f_index >= dev_data->phys_dev_properties.queue_family_properties.size()) || 8065b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis (dst_q_f_index >= dev_data->phys_dev_properties.queue_family_properties.size()))) { 8066a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 8067a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis __LINE__, DRAWSTATE_INVALID_QUEUE_INDEX, "DS", 8068cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s: Image 0x%" PRIx64 8069cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " was created with sharingMode " 8070a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis "of VK_SHARING_MODE_EXCLUSIVE, but srcQueueFamilyIndex %d" 8071a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis " or dstQueueFamilyIndex %d is greater than " PRINTF_SIZE_T_SPECIFIER 8072a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis "queueFamilies crated for this device.", 8073a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis funcName, reinterpret_cast<const uint64_t &>(mem_barrier->image), src_q_f_index, dst_q_f_index, 8074a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis dev_data->phys_dev_properties.queue_family_properties.size()); 80755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 80765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 80775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 80785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 80795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (mem_barrier) { 8080d678ec4f57d80aa89c24562e9ffe941d8d69e455Tony Barbour if (mem_barrier->oldLayout != mem_barrier->newLayout) { 8081a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis skip |= 8082d678ec4f57d80aa89c24562e9ffe941d8d69e455Tony Barbour ValidateMaskBitsFromLayouts(dev_data, cmdBuffer, mem_barrier->srcAccessMask, mem_barrier->oldLayout, "Source"); 8083a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis skip |= 8084d678ec4f57d80aa89c24562e9ffe941d8d69e455Tony Barbour ValidateMaskBitsFromLayouts(dev_data, cmdBuffer, mem_barrier->dstAccessMask, mem_barrier->newLayout, "Dest"); 8085d678ec4f57d80aa89c24562e9ffe941d8d69e455Tony Barbour } 80865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (mem_barrier->newLayout == VK_IMAGE_LAYOUT_UNDEFINED || mem_barrier->newLayout == VK_IMAGE_LAYOUT_PREINITIALIZED) { 8087a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 8088cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski DRAWSTATE_INVALID_BARRIER, "DS", 8089cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s: Image Layout cannot be transitioned to UNDEFINED or " 8090cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "PREINITIALIZED.", 8091a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis funcName); 80925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 80931d5109d5e0dcc530b27e632e73e1be5e12a28dcdJamie Madill VkFormat format = VK_FORMAT_UNDEFINED; 80941d5109d5e0dcc530b27e632e73e1be5e12a28dcdJamie Madill uint32_t arrayLayers = 0, mipLevels = 0; 80955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool imageFound = false; 80966d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis if (image_data) { 80976d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis format = image_data->createInfo.format; 80986d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis arrayLayers = image_data->createInfo.arrayLayers; 80996d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis mipLevels = image_data->createInfo.mipLevels; 81005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis imageFound = true; 81015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (dev_data->device_extensions.wsi_enabled) { 81029a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto imageswap_data = GetSwapchainFromImage(dev_data, mem_barrier->image); 8103170dc65b45f6bcdec47e02b3aa19435e55b32804Tobin Ehlis if (imageswap_data) { 81049a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto swapchain_data = GetSwapchainNode(dev_data, imageswap_data); 8105b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis if (swapchain_data) { 8106b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis format = swapchain_data->createInfo.imageFormat; 8107b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis arrayLayers = swapchain_data->createInfo.imageArrayLayers; 81085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis mipLevels = 1; 81095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis imageFound = true; 81105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 81115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 81125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 81135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (imageFound) { 8114e08b485346524a30ddfe6526f7dcbbf78c776d10Mark Lobodzinski skip |= ValidateImageSubrangeLevelLayerCounts(dev_data, mem_barrier->subresourceRange, funcName); 8115c37c65e9ff3a0abc86e706ee61d21e1dec882731Tobin Ehlis auto aspect_mask = mem_barrier->subresourceRange.aspectMask; 8116a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis skip |= ValidateImageAspectMask(dev_data, image_data->image, format, aspect_mask, funcName); 8117f0d091deca3d4b90e1f31d75e062684dca160ad1Michael Lentine int layerCount = (mem_barrier->subresourceRange.layerCount == VK_REMAINING_ARRAY_LAYERS) 8118f0d091deca3d4b90e1f31d75e062684dca160ad1Michael Lentine ? 1 8119f0d091deca3d4b90e1f31d75e062684dca160ad1Michael Lentine : mem_barrier->subresourceRange.layerCount; 8120f0d091deca3d4b90e1f31d75e062684dca160ad1Michael Lentine if ((mem_barrier->subresourceRange.baseArrayLayer + layerCount) > arrayLayers) { 8121a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 8122cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, DRAWSTATE_INVALID_BARRIER, "DS", 8123cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s: Subresource must have the sum of the " 8124cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "baseArrayLayer (%d) and layerCount (%d) be less " 8125cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "than or equal to the total number of layers (%d).", 8126a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis funcName, mem_barrier->subresourceRange.baseArrayLayer, 8127a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis mem_barrier->subresourceRange.layerCount, arrayLayers); 81285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8129f0d091deca3d4b90e1f31d75e062684dca160ad1Michael Lentine int levelCount = (mem_barrier->subresourceRange.levelCount == VK_REMAINING_MIP_LEVELS) 8130f0d091deca3d4b90e1f31d75e062684dca160ad1Michael Lentine ? 1 8131f0d091deca3d4b90e1f31d75e062684dca160ad1Michael Lentine : mem_barrier->subresourceRange.levelCount; 8132f0d091deca3d4b90e1f31d75e062684dca160ad1Michael Lentine if ((mem_barrier->subresourceRange.baseMipLevel + levelCount) > mipLevels) { 8133cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 8134cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, DRAWSTATE_INVALID_BARRIER, "DS", 8135cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s: Subresource must have the sum of the baseMipLevel " 8136cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "(%d) and levelCount (%d) be less than or equal to " 8137cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "the total number of levels (%d).", 8138cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski funcName, mem_barrier->subresourceRange.baseMipLevel, mem_barrier->subresourceRange.levelCount, 8139cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski mipLevels); 81405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 81415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 81425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 81435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 81445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < bufferBarrierCount; ++i) { 81455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto mem_barrier = &pBufferMemBarriers[i]; 81465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB->activeRenderPass) { 8147a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 8148a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis DRAWSTATE_INVALID_BARRIER, "DS", "%s: Buffer Barriers cannot be used during a render pass.", funcName); 81495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8150cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!mem_barrier) continue; 81515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 81525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Validate buffer barrier queue family indices 81535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if ((mem_barrier->srcQueueFamilyIndex != VK_QUEUE_FAMILY_IGNORED && 8154b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis mem_barrier->srcQueueFamilyIndex >= dev_data->phys_dev_properties.queue_family_properties.size()) || 81555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (mem_barrier->dstQueueFamilyIndex != VK_QUEUE_FAMILY_IGNORED && 8156b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis mem_barrier->dstQueueFamilyIndex >= dev_data->phys_dev_properties.queue_family_properties.size())) { 8157a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 8158a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis DRAWSTATE_INVALID_QUEUE_INDEX, "DS", 8159cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s: Buffer Barrier 0x%" PRIx64 8160cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " has QueueFamilyIndex greater " 8161a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis "than the number of QueueFamilies (" PRINTF_SIZE_T_SPECIFIER ") for this device.", 8162a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis funcName, reinterpret_cast<const uint64_t &>(mem_barrier->buffer), 8163a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis dev_data->phys_dev_properties.queue_family_properties.size()); 81645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 81655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 81669a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto buffer_state = GetBufferState(dev_data, mem_barrier->buffer); 81675cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis if (buffer_state) { 81685cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis auto buffer_size = buffer_state->requirements.size; 81695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (mem_barrier->offset >= buffer_size) { 8170a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 8171a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis DRAWSTATE_INVALID_BARRIER, "DS", "%s: Buffer Barrier 0x%" PRIx64 " has offset 0x%" PRIx64 8172a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis " which is not less than total size 0x%" PRIx64 ".", 8173a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis funcName, reinterpret_cast<const uint64_t &>(mem_barrier->buffer), 8174a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis reinterpret_cast<const uint64_t &>(mem_barrier->offset), 8175a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis reinterpret_cast<const uint64_t &>(buffer_size)); 81765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (mem_barrier->size != VK_WHOLE_SIZE && (mem_barrier->offset + mem_barrier->size > buffer_size)) { 8177a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis skip |= log_msg( 817894c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 8179414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller DRAWSTATE_INVALID_BARRIER, "DS", "%s: Buffer Barrier 0x%" PRIx64 " has offset 0x%" PRIx64 " and size 0x%" PRIx64 8180414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller " whose sum is greater than total size 0x%" PRIx64 ".", 818194c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis funcName, reinterpret_cast<const uint64_t &>(mem_barrier->buffer), 818294c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis reinterpret_cast<const uint64_t &>(mem_barrier->offset), reinterpret_cast<const uint64_t &>(mem_barrier->size), 818394c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis reinterpret_cast<const uint64_t &>(buffer_size)); 81845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 81855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 81865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8187a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis return skip; 81885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 81895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8190bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskibool validateEventStageMask(VkQueue queue, GLOBAL_CB_NODE *pCB, uint32_t eventCount, size_t firstEventIndex, 8191bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkPipelineStageFlags sourceStageMask) { 8192b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine bool skip_call = false; 8193b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine VkPipelineStageFlags stageMask = 0; 819456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map); 8195b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine for (uint32_t i = 0; i < eventCount; ++i) { 81962ab14387df9b890fe4b13494ea249dd03cf898d2Chris Forbes auto event = pCB->events[firstEventIndex + i]; 8197b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine auto queue_data = dev_data->queueMap.find(queue); 8198cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (queue_data == dev_data->queueMap.end()) return false; 81992ab14387df9b890fe4b13494ea249dd03cf898d2Chris Forbes auto event_data = queue_data->second.eventToStageMap.find(event); 8200b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine if (event_data != queue_data->second.eventToStageMap.end()) { 8201b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine stageMask |= event_data->second; 8202b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine } else { 82039a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto global_event_data = GetEventNode(dev_data, event); 82049556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis if (!global_event_data) { 8205b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT, 820627c3e0dda9e30d1d334728bbd373e8d7011257d4Chris Forbes reinterpret_cast<const uint64_t &>(event), __LINE__, DRAWSTATE_INVALID_EVENT, "DS", 820727c3e0dda9e30d1d334728bbd373e8d7011257d4Chris Forbes "Event 0x%" PRIx64 " cannot be waited on if it has never been set.", 82082ab14387df9b890fe4b13494ea249dd03cf898d2Chris Forbes reinterpret_cast<const uint64_t &>(event)); 8209b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine } else { 82109556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis stageMask |= global_event_data->stageMask; 8211b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine } 8212b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine } 8213b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine } 8214c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine // TODO: Need to validate that host_bit is only set if set event is called 8215c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine // but set event can be called at any time. 8216c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine if (sourceStageMask != stageMask && sourceStageMask != (stageMask | VK_PIPELINE_STAGE_HOST_BIT)) { 8217c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 8218cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VALIDATION_ERROR_00254, "DS", 8219cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Submitting cmdbuffer with call to VkCmdWaitEvents " 8220cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "using srcStageMask 0x%X which must be the bitwise " 8221cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "OR of the stageMask parameters used in calls to " 8222cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkCmdSetEvent and VK_PIPELINE_STAGE_HOST_BIT if " 8223cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "used with vkSetEvent but instead is 0x%X. %s", 82249bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt sourceStageMask, stageMask, validation_error_map[VALIDATION_ERROR_00254]); 8225b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine } 8226b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine return skip_call; 8227b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine} 8228b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine 822907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski// Note that we only check bits that HAVE required queueflags -- don't care entries are skipped 823007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinskistatic std::unordered_map<VkPipelineStageFlags, VkQueueFlags> supported_pipeline_stages_table = { 823107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX, VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT}, 823207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT}, 823307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_QUEUE_GRAPHICS_BIT}, 823407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, VK_QUEUE_GRAPHICS_BIT}, 823507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT, VK_QUEUE_GRAPHICS_BIT}, 823607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT, VK_QUEUE_GRAPHICS_BIT}, 823707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT, VK_QUEUE_GRAPHICS_BIT}, 823807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_QUEUE_GRAPHICS_BIT}, 823907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, VK_QUEUE_GRAPHICS_BIT}, 824007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_QUEUE_GRAPHICS_BIT}, 824107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_QUEUE_GRAPHICS_BIT}, 824207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_QUEUE_COMPUTE_BIT}, 824307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_TRANSFER_BIT, VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT}, 824407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_QUEUE_GRAPHICS_BIT}}; 824507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski 824607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinskistatic const VkPipelineStageFlags stage_flag_bit_array[] = {VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX, 824707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, 824807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 824907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, 825007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT, 825107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT, 825207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT, 825307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 825407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, 825507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, 825607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 825707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 825807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_TRANSFER_BIT, 825907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT}; 826007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski 826107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinskibool CheckStageMaskQueueCompatibility(layer_data *dev_data, VkCommandBuffer command_buffer, VkPipelineStageFlags stage_mask, 826207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VkQueueFlags queue_flags, const char *function, const char *src_or_dest, 826307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski UNIQUE_VALIDATION_ERROR_CODE error_code) { 826407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski bool skip = false; 826507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski // Lookup each bit in the stagemask and check for overlap between its table bits and queue_flags 826607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski for (const auto &item : stage_flag_bit_array) { 826707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski if (stage_mask & item) { 826807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski if ((supported_pipeline_stages_table[item] & queue_flags) == 0) { 826907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski skip |= 827007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 827107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski reinterpret_cast<uint64_t &>(command_buffer), __LINE__, error_code, "DL", 827207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski "%s(): %s flag %s is not compatible with the queue family properties of this " 827307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski "command buffer. %s", 827407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski function, src_or_dest, string_VkPipelineStageFlagBits(static_cast<VkPipelineStageFlagBits>(item)), 827507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski validation_error_map[error_code]); 827607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski } 827707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski } 827807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski } 827907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski return skip; 828007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski} 828107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski 828207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinskibool ValidateStageMasksAgainstQueueCapabilities(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, 828307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VkPipelineStageFlags source_stage_mask, VkPipelineStageFlags dest_stage_mask, 828407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski const char *function, UNIQUE_VALIDATION_ERROR_CODE error_code) { 828507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski bool skip = false; 828607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski uint32_t queue_family_index = dev_data->commandPoolMap[cb_state->createInfo.commandPool].queueFamilyIndex; 828756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(dev_data->physical_device), instance_layer_data_map); 82889a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto physical_device_state = GetPhysicalDeviceState(instance_data, dev_data->physical_device); 828907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski 829007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski // Any pipeline stage included in srcStageMask or dstStageMask must be supported by the capabilities of the queue family 829107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski // specified by the queueFamilyIndex member of the VkCommandPoolCreateInfo structure that was used to create the VkCommandPool 829207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski // that commandBuffer was allocated from, as specified in the table of supported pipeline stages. 829307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski 829407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski if (queue_family_index < physical_device_state->queue_family_properties.size()) { 829507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VkQueueFlags specified_queue_flags = physical_device_state->queue_family_properties[queue_family_index].queueFlags; 829607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski 829707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski if ((source_stage_mask & VK_PIPELINE_STAGE_ALL_COMMANDS_BIT) == 0) { 829807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski skip |= CheckStageMaskQueueCompatibility(dev_data, cb_state->commandBuffer, source_stage_mask, specified_queue_flags, 829907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski function, "srcStageMask", error_code); 830007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski } 830107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski if ((dest_stage_mask & VK_PIPELINE_STAGE_ALL_COMMANDS_BIT) == 0) { 830207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski skip |= CheckStageMaskQueueCompatibility(dev_data, cb_state->commandBuffer, dest_stage_mask, specified_queue_flags, 830307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski function, "dstStageMask", error_code); 830407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski } 830507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski } 830607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski return skip; 830707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski} 830807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski 8309d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent *pEvents, 8310d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski VkPipelineStageFlags sourceStageMask, VkPipelineStageFlags dstStageMask, 8311d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers, 8312d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers, 8313d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers) { 8314d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski bool skip = false; 831556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 8316b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 83179a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer); 8318d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski if (cb_state) { 8319d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski skip |= ValidateStageMasksAgainstQueueCapabilities(dev_data, cb_state, sourceStageMask, dstStageMask, "vkCmdWaitEvents", 8320d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski VALIDATION_ERROR_02510); 8321208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis skip |= ValidateStageMaskGsTsEnables(dev_data, sourceStageMask, "vkCmdWaitEvents()", VALIDATION_ERROR_02067, 8322208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis VALIDATION_ERROR_02069); 8323208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis skip |= ValidateStageMaskGsTsEnables(dev_data, dstStageMask, "vkCmdWaitEvents()", VALIDATION_ERROR_02068, 8324208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis VALIDATION_ERROR_02070); 8325d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski auto first_event_index = cb_state->events.size(); 83265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < eventCount; ++i) { 83279a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto event_state = GetEventNode(dev_data, pEvents[i]); 83284710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis if (event_state) { 83294710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis addCommandBufferBinding(&event_state->cb_bindings, 8330ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis {reinterpret_cast<const uint64_t &>(pEvents[i]), VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT}, 8331d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski cb_state); 8332d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski event_state->cb_bindings.insert(cb_state); 8333ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis } 8334d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski cb_state->waitedEvents.insert(pEvents[i]); 8335d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski cb_state->events.push_back(pEvents[i]); 83365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8337d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski std::function<bool(VkQueue)> event_update = 8338d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski std::bind(validateEventStageMask, std::placeholders::_1, cb_state, eventCount, first_event_index, sourceStageMask); 8339d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski cb_state->eventUpdates.push_back(event_update); 8340d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski if (cb_state->state == CB_RECORDING) { 834129f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip |= ValidateCmd(dev_data, cb_state, CMD_WAITEVENTS, "vkCmdWaitEvents()"); 83421ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(cb_state, CMD_WAITEVENTS); 83435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 8344d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski skip |= report_error_no_cb_begin(dev_data, commandBuffer, "vkCmdWaitEvents()"); 83455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 834655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski skip |= TransitionImageLayouts(dev_data, commandBuffer, imageMemoryBarrierCount, pImageMemoryBarriers); 8347364a03b109f0b2b37be2e13d293fa93b8af5203aMike Weiblen skip |= ValidateBarriers("vkCmdWaitEvents()", commandBuffer, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, 8348d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers); 83495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8350b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 8351d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski if (!skip) 83524a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdWaitEvents(commandBuffer, eventCount, pEvents, sourceStageMask, dstStageMask, 83534a0754042cf090e131e9e769d8a3633c228625beChris Forbes memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, 83544a0754042cf090e131e9e769d8a3633c228625beChris Forbes imageMemoryBarrierCount, pImageMemoryBarriers); 83555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 83565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8357d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdPipelineBarrier(VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask, 8358d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags, 8359d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers, 8360d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers, 8361d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers) { 8362d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski bool skip = false; 836356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 8364b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 83659a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer); 8366d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski if (cb_state) { 8367d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski skip |= ValidateStageMasksAgainstQueueCapabilities(dev_data, cb_state, srcStageMask, dstStageMask, "vkCmdPipelineBarrier", 8368d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski VALIDATION_ERROR_02513); 836929f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip |= ValidateCmd(dev_data, cb_state, CMD_PIPELINEBARRIER, "vkCmdPipelineBarrier()"); 8370208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis skip |= ValidateStageMaskGsTsEnables(dev_data, srcStageMask, "vkCmdPipelineBarrier()", VALIDATION_ERROR_00265, 8371208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis VALIDATION_ERROR_00267); 8372208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis skip |= ValidateStageMaskGsTsEnables(dev_data, dstStageMask, "vkCmdPipelineBarrier()", VALIDATION_ERROR_00266, 8373208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis VALIDATION_ERROR_00268); 83741ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(cb_state, CMD_PIPELINEBARRIER); 837555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski skip |= TransitionImageLayouts(dev_data, commandBuffer, imageMemoryBarrierCount, pImageMemoryBarriers); 8376364a03b109f0b2b37be2e13d293fa93b8af5203aMike Weiblen skip |= ValidateBarriers("vkCmdPipelineBarrier()", commandBuffer, memoryBarrierCount, pMemoryBarriers, 8377d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers); 83785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8379b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 8380d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski if (!skip) 83814a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, memoryBarrierCount, 83824a0754042cf090e131e9e769d8a3633c228625beChris Forbes pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, 83834a0754042cf090e131e9e769d8a3633c228625beChris Forbes imageMemoryBarrierCount, pImageMemoryBarriers); 83845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 83855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8386d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentinebool setQueryState(VkQueue queue, VkCommandBuffer commandBuffer, QueryObject object, bool value) { 838756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 83889a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 8389d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine if (pCB) { 8390d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine pCB->queryToStateMap[object] = value; 8391d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 8392d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine auto queue_data = dev_data->queueMap.find(queue); 8393d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine if (queue_data != dev_data->queueMap.end()) { 8394d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine queue_data->second.queryToStateMap[object] = value; 8395d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 8396d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine return false; 8397d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine} 8398d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine 8399bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBeginQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t slot, VkFlags flags) { 840083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 840156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 8402b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 84039a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 84045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 84055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis QueryObject query = {queryPool, slot}; 84065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->activeQueries.insert(query); 84075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!pCB->startedQueries.count(query)) { 84085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->startedQueries.insert(query); 84095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 841029f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_BEGINQUERY, "vkCmdBeginQuery()"); 84111ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_BEGINQUERY); 84129a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis addCommandBufferBinding(&GetQueryPoolNode(dev_data, queryPool)->cb_bindings, 8413ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis {reinterpret_cast<uint64_t &>(queryPool), VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT}, pCB); 84145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8415b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 8416cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.CmdBeginQuery(commandBuffer, queryPool, slot, flags); 84175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 84185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 841989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdEndQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t slot) { 842083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 842156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 8422b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 84239a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 84245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 84255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis QueryObject query = {queryPool, slot}; 84265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!pCB->activeQueries.count(query)) { 842783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= 84285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 84299bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt VALIDATION_ERROR_01041, "DS", "Ending a query before it was started: queryPool 0x%" PRIx64 ", index %d. %s", 84309bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt (uint64_t)(queryPool), slot, validation_error_map[VALIDATION_ERROR_01041]); 84315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 84325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->activeQueries.erase(query); 84335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8434c2ec509029604290e981885108c06a9b7de565c1Karl Schultz std::function<bool(VkQueue)> queryUpdate = std::bind(setQueryState, std::placeholders::_1, commandBuffer, query, true); 8435d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine pCB->queryUpdates.push_back(queryUpdate); 84365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB->state == CB_RECORDING) { 843729f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_ENDQUERY, "VkCmdEndQuery()"); 84381ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_ENDQUERY); 84395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 844083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= report_error_no_cb_begin(dev_data, commandBuffer, "vkCmdEndQuery()"); 84415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 84429a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis addCommandBufferBinding(&GetQueryPoolNode(dev_data, queryPool)->cb_bindings, 8443ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis {reinterpret_cast<uint64_t &>(queryPool), VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT}, pCB); 84445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8445b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 8446cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.CmdEndQuery(commandBuffer, queryPool, slot); 84475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 84485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8449bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdResetQueryPool(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, 8450bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski uint32_t queryCount) { 845183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 845256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 8453b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 84549a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 84555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 84565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < queryCount; i++) { 84575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis QueryObject query = {queryPool, firstQuery + i}; 84585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->waitedEventsBeforeQueryReset[query] = pCB->waitedEvents; 8459c2ec509029604290e981885108c06a9b7de565c1Karl Schultz std::function<bool(VkQueue)> queryUpdate = std::bind(setQueryState, std::placeholders::_1, commandBuffer, query, false); 8460d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine pCB->queryUpdates.push_back(queryUpdate); 84615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 84625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB->state == CB_RECORDING) { 846329f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_RESETQUERYPOOL, "VkCmdResetQueryPool()"); 84641ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_RESETQUERYPOOL); 84655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 846683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= report_error_no_cb_begin(dev_data, commandBuffer, "vkCmdResetQueryPool()"); 84675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8468ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen skip_call |= insideRenderPass(dev_data, pCB, "vkCmdResetQueryPool()", VALIDATION_ERROR_01025); 84699a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis addCommandBufferBinding(&GetQueryPoolNode(dev_data, queryPool)->cb_bindings, 8470ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis {reinterpret_cast<uint64_t &>(queryPool), VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT}, pCB); 84715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8472b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 8473cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.CmdResetQueryPool(commandBuffer, queryPool, firstQuery, queryCount); 84745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 84755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8476d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentinebool validateQuery(VkQueue queue, GLOBAL_CB_NODE *pCB, VkQueryPool queryPool, uint32_t queryCount, uint32_t firstQuery) { 8477d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine bool skip_call = false; 847856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(pCB->commandBuffer), layer_data_map); 8479d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine auto queue_data = dev_data->queueMap.find(queue); 8480cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (queue_data == dev_data->queueMap.end()) return false; 8481d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine for (uint32_t i = 0; i < queryCount; i++) { 8482d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine QueryObject query = {queryPool, firstQuery + i}; 8483d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine auto query_data = queue_data->second.queryToStateMap.find(query); 8484d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine bool fail = false; 8485d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine if (query_data != queue_data->second.queryToStateMap.end()) { 8486d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine if (!query_data->second) { 8487d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine fail = true; 8488d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 8489d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } else { 8490d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine auto global_query_data = dev_data->queryToStateMap.find(query); 8491d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine if (global_query_data != dev_data->queryToStateMap.end()) { 8492d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine if (!global_query_data->second) { 8493d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine fail = true; 8494d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 8495d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } else { 8496d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine fail = true; 8497d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 8498d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 8499d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine if (fail) { 8500d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 8501d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine DRAWSTATE_INVALID_QUERY, "DS", 8502d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine "Requesting a copy from query to buffer with invalid query: queryPool 0x%" PRIx64 ", index %d", 8503d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine reinterpret_cast<uint64_t &>(queryPool), firstQuery + i); 8504d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 8505d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 8506d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine return skip_call; 8507d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine} 8508d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine 8509bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdCopyQueryPoolResults(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, 8510bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski uint32_t queryCount, VkBuffer dstBuffer, VkDeviceSize dstOffset, 8511bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDeviceSize stride, VkQueryResultFlags flags) { 851283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 851356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 8514b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 8515ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis 85169a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, commandBuffer); 85179a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto dst_buff_state = GetBufferState(dev_data, dstBuffer); 85185cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis if (cb_node && dst_buff_state) { 851935ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, dst_buff_state, "vkCmdCopyQueryPoolResults()", VALIDATION_ERROR_02526); 8520ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis // Update bindings between buffer and cmd buffer 85215cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis AddCommandBufferBindingBuffer(dev_data, cb_node, dst_buff_state); 8522ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis // Validate that DST buffer has correct usage flags set 85231b8a6bd9260c52ca6c6cfe1e34f142f93e1e2cc6Jeremy Hayes skip_call |= 85245cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis ValidateBufferUsageFlags(dev_data, dst_buff_state, VK_BUFFER_USAGE_TRANSFER_DST_BIT, true, VALIDATION_ERROR_01066, 85251b8a6bd9260c52ca6c6cfe1e34f142f93e1e2cc6Jeremy Hayes "vkCmdCopyQueryPoolResults()", "VK_BUFFER_USAGE_TRANSFER_DST_BIT"); 8526e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves std::function<bool()> function = [=]() { 85275cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis SetBufferMemoryValid(dev_data, dst_buff_state, true); 8528e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves return false; 85295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis }; 85309f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis cb_node->validate_functions.push_back(function); 8531d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine std::function<bool(VkQueue)> queryUpdate = 8532ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis std::bind(validateQuery, std::placeholders::_1, cb_node, queryPool, queryCount, firstQuery); 8533ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis cb_node->queryUpdates.push_back(queryUpdate); 8534ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis if (cb_node->state == CB_RECORDING) { 853529f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, cb_node, CMD_COPYQUERYPOOLRESULTS, "vkCmdCopyQueryPoolResults()"); 85361ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(cb_node, CMD_COPYQUERYPOOLRESULTS); 85375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 853883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= report_error_no_cb_begin(dev_data, commandBuffer, "vkCmdCopyQueryPoolResults()"); 85395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8540ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen skip_call |= insideRenderPass(dev_data, cb_node, "vkCmdCopyQueryPoolResults()", VALIDATION_ERROR_01074); 85419a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis addCommandBufferBinding(&GetQueryPoolNode(dev_data, queryPool)->cb_bindings, 8542ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis {reinterpret_cast<uint64_t &>(queryPool), VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT}, cb_node); 8543ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } else { 8544ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis assert(0); 85455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8546b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 854783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis if (!skip_call) 85484a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdCopyQueryPoolResults(commandBuffer, queryPool, firstQuery, queryCount, dstBuffer, dstOffset, 85494a0754042cf090e131e9e769d8a3633c228625beChris Forbes stride, flags); 85505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 85515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8552bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdPushConstants(VkCommandBuffer commandBuffer, VkPipelineLayout layout, VkShaderStageFlags stageFlags, 8553bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski uint32_t offset, uint32_t size, const void *pValues) { 855483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 855556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 8556b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 85579a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 85585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 85595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB->state == CB_RECORDING) { 856029f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_PUSHCONSTANTS, "vkCmdPushConstants()"); 85611ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_PUSHCONSTANTS); 85625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 856383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= report_error_no_cb_begin(dev_data, commandBuffer, "vkCmdPushConstants()"); 85645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 85655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 856683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= validatePushConstantRange(dev_data, offset, size, "vkCmdPushConstants()"); 85679e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz if (0 == stageFlags) { 856883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 85699bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt VALIDATION_ERROR_00996, "DS", "vkCmdPushConstants() call has no stageFlags set. %s", 85709bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt validation_error_map[VALIDATION_ERROR_00996]); 85719e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 85729e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz 8573a95cb74c9d0947ab3821b15e1289755286ea78eeKarl Schultz // Check if push constant update is within any of the ranges with the same stage flags specified in pipeline layout. 8574c2a5a36d03bbe52f5854a5884346e4a84115e259Tobin Ehlis auto pipeline_layout = getPipelineLayout(dev_data, layout); 857515a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis // Coalesce adjacent/overlapping pipeline ranges before checking to see if incoming range is 857615a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis // contained in the pipeline ranges. 857715a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis // Build a {start, end} span list for ranges with matching stage flags. 857815a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis const auto &ranges = pipeline_layout->push_constant_ranges; 857915a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis struct span { 858015a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis uint32_t start; 858115a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis uint32_t end; 858215a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis }; 858315a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis std::vector<span> spans; 858415a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis spans.reserve(ranges.size()); 858515a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis for (const auto &iter : ranges) { 858615a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis if (iter.stageFlags == stageFlags) { 858715a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis spans.push_back({iter.offset, iter.offset + iter.size}); 858815a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis } 858915a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis } 859015a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis if (spans.size() == 0) { 859115a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis // There were no ranges that matched the stageFlags. 859215a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis skip_call |= 859315a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 8594cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VALIDATION_ERROR_00988, "DS", "vkCmdPushConstants() stageFlags = 0x%" PRIx32 8595cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " do not match " 85969bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "the stageFlags in any of the ranges in pipeline layout 0x%" PRIx64 ". %s", 85979bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt (uint32_t)stageFlags, (uint64_t)layout, validation_error_map[VALIDATION_ERROR_00988]); 85989e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } else { 859915a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis // Sort span list by start value. 860015a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis struct comparer { 860115a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis bool operator()(struct span i, struct span j) { return i.start < j.start; } 860215a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis } my_comparer; 860315a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis std::sort(spans.begin(), spans.end(), my_comparer); 860415a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis 860515a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis // Examine two spans at a time. 860615a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis std::vector<span>::iterator current = spans.begin(); 860715a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis std::vector<span>::iterator next = current + 1; 860815a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis while (next != spans.end()) { 860915a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis if (current->end < next->start) { 861015a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis // There is a gap; cannot coalesce. Move to the next two spans. 861115a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis ++current; 861215a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis ++next; 861315a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis } else { 861415a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis // Coalesce the two spans. The start of the next span 861515a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis // is within the current span, so pick the larger of 861615a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis // the end values to extend the current span. 861715a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis // Then delete the next span and set next to the span after it. 861815a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis current->end = max(current->end, next->end); 861915a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis next = spans.erase(next); 86209e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 86219e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 8622a95cb74c9d0947ab3821b15e1289755286ea78eeKarl Schultz 862315a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis // Now we can check if the incoming range is within any of the spans. 862415a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis bool contained_in_a_range = false; 862515a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis for (uint32_t i = 0; i < spans.size(); ++i) { 862615a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis if ((offset >= spans[i].start) && ((uint64_t)offset + (uint64_t)size <= (uint64_t)spans[i].end)) { 862715a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis contained_in_a_range = true; 862815a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis break; 8629a95cb74c9d0947ab3821b15e1289755286ea78eeKarl Schultz } 86309e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 863115a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis if (!contained_in_a_range) { 8632cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 8633cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VALIDATION_ERROR_00988, "DS", 8634cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkCmdPushConstants() Push constant range [%d, %d) " 8635cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "with stageFlags = 0x%" PRIx32 8636cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " " 8637cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "not within flag-matching ranges in pipeline layout 0x%" PRIx64 ". %s", 8638cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski offset, offset + size, (uint32_t)stageFlags, (uint64_t)layout, 8639cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski validation_error_map[VALIDATION_ERROR_00988]); 864015a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis } 86415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8642b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 8643cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.CmdPushConstants(commandBuffer, layout, stageFlags, offset, size, pValues); 86445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 86455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8646bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdWriteTimestamp(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, 8647bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkQueryPool queryPool, uint32_t slot) { 864883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 864956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 8650b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 86519a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 86525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 86535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis QueryObject query = {queryPool, slot}; 8654c2ec509029604290e981885108c06a9b7de565c1Karl Schultz std::function<bool(VkQueue)> queryUpdate = std::bind(setQueryState, std::placeholders::_1, commandBuffer, query, true); 8655d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine pCB->queryUpdates.push_back(queryUpdate); 86565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB->state == CB_RECORDING) { 865729f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_WRITETIMESTAMP, "vkCmdWriteTimestamp()"); 86581ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_WRITETIMESTAMP); 86595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 866083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= report_error_no_cb_begin(dev_data, commandBuffer, "vkCmdWriteTimestamp()"); 86615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 86625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8663b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 8664cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.CmdWriteTimestamp(commandBuffer, pipelineStage, queryPool, slot); 86655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 86665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 86676600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinskistatic bool MatchUsage(layer_data *dev_data, uint32_t count, const VkAttachmentReference *attachments, 86689bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt const VkFramebufferCreateInfo *fbci, VkImageUsageFlagBits usage_flag, 86699bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt UNIQUE_VALIDATION_ERROR_CODE error_code) { 86706600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski bool skip_call = false; 86716600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski 86726600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski for (uint32_t attach = 0; attach < count; attach++) { 86736600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski if (attachments[attach].attachment != VK_ATTACHMENT_UNUSED) { 86746600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski // Attachment counts are verified elsewhere, but prevent an invalid access 86756600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski if (attachments[attach].attachment < fbci->attachmentCount) { 86766600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski const VkImageView *image_view = &fbci->pAttachments[attachments[attach].attachment]; 86779a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto view_state = GetImageViewState(dev_data, *image_view); 867879fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis if (view_state) { 86799a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis const VkImageCreateInfo *ici = &GetImageState(dev_data, view_state->create_info.image)->createInfo; 86806600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski if (ici != nullptr) { 86816600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski if ((ici->usage & usage_flag) == 0) { 86826600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 86839bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt (VkDebugReportObjectTypeEXT)0, 0, __LINE__, error_code, "DS", 86846600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski "vkCreateFramebuffer: Framebuffer Attachment (%d) conflicts with the image's " 86859bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "IMAGE_USAGE flags (%s). %s", 86869bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt attachments[attach].attachment, string_VkImageUsageFlagBits(usage_flag), 86879bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt validation_error_map[error_code]); 86886600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski } 86896600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski } 86906600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski } 86916600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski } 86926600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski } 86936600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski } 86946600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski return skip_call; 86956600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski} 86966600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski 8697d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis// Validate VkFramebufferCreateInfo which includes: 8698d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis// 1. attachmentCount equals renderPass attachmentCount 86995ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 2. corresponding framebuffer and renderpass attachments have matching formats 87005ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 3. corresponding framebuffer and renderpass attachments have matching sample counts 87015ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 4. fb attachments only have a single mip level 87025ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 5. fb attachment dimensions are each at least as large as the fb 87035ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 6. fb attachments use idenity swizzle 87045ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 7. fb attachments used by renderPass for color/input/ds have correct usage bit set 87056fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis// 8. fb dimensions are within physical device limits 8706d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlisstatic bool ValidateFramebufferCreateInfo(layer_data *dev_data, const VkFramebufferCreateInfo *pCreateInfo) { 87076600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski bool skip_call = false; 87086600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski 87099a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto rp_state = GetRenderPassState(dev_data, pCreateInfo->renderPass); 8710127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis if (rp_state) { 8711127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis const VkRenderPassCreateInfo *rpci = rp_state->createInfo.ptr(); 8712d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis if (rpci->attachmentCount != pCreateInfo->attachmentCount) { 8713d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis skip_call |= log_msg( 8714d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT, 87159bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt reinterpret_cast<const uint64_t &>(pCreateInfo->renderPass), __LINE__, VALIDATION_ERROR_00404, "DS", 8716d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis "vkCreateFramebuffer(): VkFramebufferCreateInfo attachmentCount of %u does not match attachmentCount of %u of " 87179bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "renderPass (0x%" PRIxLEAST64 ") being used to create Framebuffer. %s", 87189bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt pCreateInfo->attachmentCount, rpci->attachmentCount, reinterpret_cast<const uint64_t &>(pCreateInfo->renderPass), 87199bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt validation_error_map[VALIDATION_ERROR_00404]); 87205ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis } else { 872141ebcb6b517b1de5ae456d46d866f5e84a96a2c5Tobin Ehlis // attachmentCounts match, so make sure corresponding attachment details line up 87225ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis const VkImageView *image_views = pCreateInfo->pAttachments; 87235ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) { 87249a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto view_state = GetImageViewState(dev_data, image_views[i]); 872512d5600c2f9e32343016fd944432ba95df370797Tobin Ehlis auto &ivci = view_state->create_info; 872679fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis if (ivci.format != rpci->pAttachments[i].format) { 87275ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis skip_call |= log_msg( 87285ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT, 87299bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt reinterpret_cast<const uint64_t &>(pCreateInfo->renderPass), __LINE__, VALIDATION_ERROR_00408, "DS", 87309bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "vkCreateFramebuffer(): VkFramebufferCreateInfo attachment #%u has format of %s that does not match " 87319bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "the format of " 87329bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "%s used by the corresponding attachment for renderPass (0x%" PRIxLEAST64 "). %s", 873379fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis i, string_VkFormat(ivci.format), string_VkFormat(rpci->pAttachments[i].format), 87349bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt reinterpret_cast<const uint64_t &>(pCreateInfo->renderPass), validation_error_map[VALIDATION_ERROR_00408]); 87355ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis } 87369a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis const VkImageCreateInfo *ici = &GetImageState(dev_data, ivci.image)->createInfo; 87375ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis if (ici->samples != rpci->pAttachments[i].samples) { 873841ebcb6b517b1de5ae456d46d866f5e84a96a2c5Tobin Ehlis skip_call |= log_msg( 873941ebcb6b517b1de5ae456d46d866f5e84a96a2c5Tobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT, 87409bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt reinterpret_cast<const uint64_t &>(pCreateInfo->renderPass), __LINE__, VALIDATION_ERROR_00409, "DS", 87419bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "vkCreateFramebuffer(): VkFramebufferCreateInfo attachment #%u has %s samples that do not match " 87429bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "the %s samples used by the corresponding attachment for renderPass (0x%" PRIxLEAST64 "). %s", 874341ebcb6b517b1de5ae456d46d866f5e84a96a2c5Tobin Ehlis i, string_VkSampleCountFlagBits(ici->samples), string_VkSampleCountFlagBits(rpci->pAttachments[i].samples), 87449bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt reinterpret_cast<const uint64_t &>(pCreateInfo->renderPass), validation_error_map[VALIDATION_ERROR_00409]); 87455ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis } 87465ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis // Verify that view only has a single mip level 874779fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis if (ivci.subresourceRange.levelCount != 1) { 87489bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt skip_call |= 87499bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 87509bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt VALIDATION_ERROR_00411, "DS", 87519bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "vkCreateFramebuffer(): VkFramebufferCreateInfo attachment #%u has mip levelCount of %u " 87529bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "but only a single mip level (levelCount == 1) is allowed when creating a Framebuffer. %s", 87539bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt i, ivci.subresourceRange.levelCount, validation_error_map[VALIDATION_ERROR_00411]); 87545ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis } 875579fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis const uint32_t mip_level = ivci.subresourceRange.baseMipLevel; 8756aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis uint32_t mip_width = max(1u, ici->extent.width >> mip_level); 8757aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis uint32_t mip_height = max(1u, ici->extent.height >> mip_level); 875879fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis if ((ivci.subresourceRange.layerCount < pCreateInfo->layers) || (mip_width < pCreateInfo->width) || 8759aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis (mip_height < pCreateInfo->height)) { 8760aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis skip_call |= 87616fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 8762aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis DRAWSTATE_INVALID_FRAMEBUFFER_CREATE_INFO, "DS", 8763aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis "vkCreateFramebuffer(): VkFramebufferCreateInfo attachment #%u mip level %u has dimensions smaller " 8764aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis "than the corresponding " 8765aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis "framebuffer dimensions. Attachment dimensions must be at least as large. Here are the respective " 8766aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis "dimensions for " 8767aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis "attachment #%u, framebuffer:\n" 8768aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis "width: %u, %u\n" 8769aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis "height: %u, %u\n" 8770aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis "layerCount: %u, %u\n", 877179fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis i, ivci.subresourceRange.baseMipLevel, i, mip_width, pCreateInfo->width, mip_height, 877279fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis pCreateInfo->height, ivci.subresourceRange.layerCount, pCreateInfo->layers); 87735ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis } 877479fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis if (((ivci.components.r != VK_COMPONENT_SWIZZLE_IDENTITY) && (ivci.components.r != VK_COMPONENT_SWIZZLE_R)) || 877579fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis ((ivci.components.g != VK_COMPONENT_SWIZZLE_IDENTITY) && (ivci.components.g != VK_COMPONENT_SWIZZLE_G)) || 877679fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis ((ivci.components.b != VK_COMPONENT_SWIZZLE_IDENTITY) && (ivci.components.b != VK_COMPONENT_SWIZZLE_B)) || 877779fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis ((ivci.components.a != VK_COMPONENT_SWIZZLE_IDENTITY) && (ivci.components.a != VK_COMPONENT_SWIZZLE_A))) { 8778da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis skip_call |= log_msg( 87796fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 87809bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt VALIDATION_ERROR_00412, "DS", 8781da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis "vkCreateFramebuffer(): VkFramebufferCreateInfo attachment #%u has non-identy swizzle. All framebuffer " 8782da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis "attachments must have been created with the identity swizzle. Here are the actual swizzle values:\n" 8783da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis "r swizzle = %s\n" 8784da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis "g swizzle = %s\n" 8785da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis "b swizzle = %s\n" 87869bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "a swizzle = %s\n" 87879bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "%s", 878879fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis i, string_VkComponentSwizzle(ivci.components.r), string_VkComponentSwizzle(ivci.components.g), 87899bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt string_VkComponentSwizzle(ivci.components.b), string_VkComponentSwizzle(ivci.components.a), 87909bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt validation_error_map[VALIDATION_ERROR_00412]); 87915ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis } 87925ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis } 8793d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis } 87945ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis // Verify correct attachment usage flags 87956600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski for (uint32_t subpass = 0; subpass < rpci->subpassCount; subpass++) { 87966600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski // Verify input attachments: 87979bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt skip_call |= 87989bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt MatchUsage(dev_data, rpci->pSubpasses[subpass].inputAttachmentCount, rpci->pSubpasses[subpass].pInputAttachments, 87999bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt pCreateInfo, VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT, VALIDATION_ERROR_00407); 88006600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski // Verify color attachments: 88019bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt skip_call |= 88029bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt MatchUsage(dev_data, rpci->pSubpasses[subpass].colorAttachmentCount, rpci->pSubpasses[subpass].pColorAttachments, 88039bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt pCreateInfo, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VALIDATION_ERROR_00405); 88046600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski // Verify depth/stencil attachments: 88056600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski if (rpci->pSubpasses[subpass].pDepthStencilAttachment != nullptr) { 88066600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski skip_call |= MatchUsage(dev_data, 1, rpci->pSubpasses[subpass].pDepthStencilAttachment, pCreateInfo, 88079bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VALIDATION_ERROR_00406); 88086600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski } 88096600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski } 88106600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski } 88116fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis // Verify FB dimensions are within physical device limits 88129bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt if (pCreateInfo->width > dev_data->phys_dev_properties.properties.limits.maxFramebufferWidth) { 88136fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 88149bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt VALIDATION_ERROR_00413, "DS", 88159bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "vkCreateFramebuffer(): Requested VkFramebufferCreateInfo width exceeds physical device limits. " 88169bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "Requested width: %u, device max: %u\n" 88179bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "%s", 88186fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis pCreateInfo->width, dev_data->phys_dev_properties.properties.limits.maxFramebufferWidth, 88199bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt validation_error_map[VALIDATION_ERROR_00413]); 88209bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt } 88219bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt if (pCreateInfo->height > dev_data->phys_dev_properties.properties.limits.maxFramebufferHeight) { 88229bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 88239bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt VALIDATION_ERROR_00414, "DS", 88249bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "vkCreateFramebuffer(): Requested VkFramebufferCreateInfo height exceeds physical device limits. " 88259bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "Requested height: %u, device max: %u\n" 88269bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "%s", 88276fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis pCreateInfo->height, dev_data->phys_dev_properties.properties.limits.maxFramebufferHeight, 88289bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt validation_error_map[VALIDATION_ERROR_00414]); 88299bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt } 88309bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt if (pCreateInfo->layers > dev_data->phys_dev_properties.properties.limits.maxFramebufferLayers) { 88319bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 88329bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt VALIDATION_ERROR_00415, "DS", 88339bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "vkCreateFramebuffer(): Requested VkFramebufferCreateInfo layers exceeds physical device limits. " 88349bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "Requested layers: %u, device max: %u\n" 88359bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "%s", 88369bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt pCreateInfo->layers, dev_data->phys_dev_properties.properties.limits.maxFramebufferLayers, 88379bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt validation_error_map[VALIDATION_ERROR_00415]); 88386fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis } 88396600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski return skip_call; 88406600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski} 88416600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski 884264c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis// Validate VkFramebufferCreateInfo state prior to calling down chain to create Framebuffer object 884364c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis// Return true if an error is encountered and callback returns true to skip call down chain 884464c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis// false indicates that call down chain should proceed 884564c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlisstatic bool PreCallValidateCreateFramebuffer(layer_data *dev_data, const VkFramebufferCreateInfo *pCreateInfo) { 884664c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis // TODO : Verify that renderPass FB is created with is compatible with FB 884764c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis bool skip_call = false; 8848d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis skip_call |= ValidateFramebufferCreateInfo(dev_data, pCreateInfo); 884964c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis return skip_call; 885064c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis} 885164c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis 885254e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis// CreateFramebuffer state has been validated and call down chain completed so record new framebuffer object 885354e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlisstatic void PostCallRecordCreateFramebuffer(layer_data *dev_data, const VkFramebufferCreateInfo *pCreateInfo, VkFramebuffer fb) { 885454e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis // Shadow create info and store in map 8855c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis std::unique_ptr<FRAMEBUFFER_STATE> fb_state( 8856c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis new FRAMEBUFFER_STATE(fb, pCreateInfo, dev_data->renderPassMap[pCreateInfo->renderPass]->createInfo.ptr())); 885776f04ca0e692f9f15d5ef7e0c658c24d11f34ebcTobin Ehlis 885854e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) { 885954e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis VkImageView view = pCreateInfo->pAttachments[i]; 88609a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto view_state = GetImageViewState(dev_data, view); 886179fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis if (!view_state) { 886254e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis continue; 886354e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis } 886454e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis MT_FB_ATTACHMENT_INFO fb_info; 88659a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis fb_info.mem = GetImageState(dev_data, view_state->create_info.image)->binding.mem; 8866883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis fb_info.view_state = view_state; 886779fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis fb_info.image = view_state->create_info.image; 8868c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis fb_state->attachments.push_back(fb_info); 886954e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis } 8870c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis dev_data->frameBufferMap[fb] = std::move(fb_state); 887154e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis} 887254e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis 887389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateFramebuffer(VkDevice device, const VkFramebufferCreateInfo *pCreateInfo, 8874bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkFramebuffer *pFramebuffer) { 887556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 887664c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 887764c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis bool skip_call = PreCallValidateCreateFramebuffer(dev_data, pCreateInfo); 887864c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis lock.unlock(); 887964c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis 8880cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip_call) return VK_ERROR_VALIDATION_FAILED_EXT; 888164c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis 88824a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateFramebuffer(device, pCreateInfo, pAllocator, pFramebuffer); 88836600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski 88845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 888564c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis lock.lock(); 888654e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis PostCallRecordCreateFramebuffer(dev_data, pCreateInfo, *pFramebuffer); 888754e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis lock.unlock(); 88885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 88895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 88905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 88915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8892e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool FindDependency(const int index, const int dependent, const std::vector<DAGNode> &subpass_to_node, 8893e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves std::unordered_set<uint32_t> &processed_nodes) { 88945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // If we have already checked this node we have not found a dependency path so return false. 8895cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (processed_nodes.count(index)) return false; 88965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis processed_nodes.insert(index); 88975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const DAGNode &node = subpass_to_node[index]; 88985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Look for a dependency path. If one exists return true else recurse on the previous nodes. 8899593f84b63934f07483e5e5a20fd352df8ab4f8c9Bruce Dawson if (std::find(node.prev.begin(), node.prev.end(), static_cast<uint32_t>(dependent)) == node.prev.end()) { 89005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto elem : node.prev) { 8901cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (FindDependency(elem, dependent, subpass_to_node, processed_nodes)) return true; 89025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 89035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 8904e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves return true; 89055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8906e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves return false; 89075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 89085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 89098860b85a52096f9f9b28616bc37feed505497a54Chris Forbesstatic bool CheckDependencyExists(const layer_data *dev_data, const int subpass, const std::vector<uint32_t> &dependent_subpasses, 8910e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves const std::vector<DAGNode> &subpass_to_node, bool &skip_call) { 8911e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool result = true; 89125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Loop through all subpasses that share the same attachment and make sure a dependency exists 89135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t k = 0; k < dependent_subpasses.size(); ++k) { 8914cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (static_cast<uint32_t>(subpass) == dependent_subpasses[k]) continue; 89155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const DAGNode &node = subpass_to_node[subpass]; 89165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Check for a specified dependency between the two nodes. If one exists we are done. 89175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto prev_elem = std::find(node.prev.begin(), node.prev.end(), dependent_subpasses[k]); 89185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto next_elem = std::find(node.next.begin(), node.next.end(), dependent_subpasses[k]); 89195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (prev_elem == node.prev.end() && next_elem == node.next.end()) { 89207655cb8b5eb52badee0b011729a05afa36316d69Jan-Harald Fredriksen // If no dependency exits an implicit dependency still might. If not, throw an error. 89215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_set<uint32_t> processed_nodes; 89227655cb8b5eb52badee0b011729a05afa36316d69Jan-Harald Fredriksen if (!(FindDependency(subpass, dependent_subpasses[k], subpass_to_node, processed_nodes) || 8923bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski FindDependency(dependent_subpasses[k], subpass, subpass_to_node, processed_nodes))) { 89248860b85a52096f9f9b28616bc37feed505497a54Chris Forbes skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 89255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS", 89265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis "A dependency between subpasses %d and %d must exist but one is not specified.", subpass, 89275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dependent_subpasses[k]); 8928e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves result = false; 89295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 89305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 89315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 89325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 89335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 89345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 89358860b85a52096f9f9b28616bc37feed505497a54Chris Forbesstatic bool CheckPreserved(const layer_data *dev_data, const VkRenderPassCreateInfo *pCreateInfo, const int index, 8936e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves const uint32_t attachment, const std::vector<DAGNode> &subpass_to_node, int depth, bool &skip_call) { 89375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const DAGNode &node = subpass_to_node[index]; 89385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // If this node writes to the attachment return true as next nodes need to preserve the attachment. 89395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[index]; 89405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) { 8941cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (attachment == subpass.pColorAttachments[j].attachment) return true; 89425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8943a4ea781e8fff70c9db0bedad7fcb6bba08e35da7Tony Barbour for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) { 8944a4ea781e8fff70c9db0bedad7fcb6bba08e35da7Tony Barbour if (attachment == subpass.pInputAttachments[j].attachment) return true; 8945a4ea781e8fff70c9db0bedad7fcb6bba08e35da7Tony Barbour } 89465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) { 8947cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (attachment == subpass.pDepthStencilAttachment->attachment) return true; 89485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8949e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool result = false; 89505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Loop through previous nodes and see if any of them write to the attachment. 89515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto elem : node.prev) { 89528860b85a52096f9f9b28616bc37feed505497a54Chris Forbes result |= CheckPreserved(dev_data, pCreateInfo, elem, attachment, subpass_to_node, depth + 1, skip_call); 89535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 89545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // If the attachment was written to by a previous node than this node needs to preserve it. 89555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (result && depth > 0) { 8956e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool has_preserved = false; 89575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t j = 0; j < subpass.preserveAttachmentCount; ++j) { 89585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (subpass.pPreserveAttachments[j] == attachment) { 8959e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves has_preserved = true; 89605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis break; 89615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 89625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8963e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves if (!has_preserved) { 89645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis skip_call |= 89658860b85a52096f9f9b28616bc37feed505497a54Chris Forbes log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 89665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis DRAWSTATE_INVALID_RENDERPASS, "DS", 89675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis "Attachment %d is used by a later subpass and must be preserved in subpass %d.", attachment, index); 89685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 89695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 89705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 89715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 89725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8973cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskitemplate <class T> 8974cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskibool isRangeOverlapping(T offset1, T size1, T offset2, T size2) { 89755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return (((offset1 + size1) > offset2) && ((offset1 + size1) < (offset2 + size2))) || 89765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis ((offset1 > offset2) && (offset1 < (offset2 + size2))); 89775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 89785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 89795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisbool isRegionOverlapping(VkImageSubresourceRange range1, VkImageSubresourceRange range2) { 89805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return (isRangeOverlapping(range1.baseMipLevel, range1.levelCount, range2.baseMipLevel, range2.levelCount) && 89815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis isRangeOverlapping(range1.baseArrayLayer, range1.layerCount, range2.baseArrayLayer, range2.layerCount)); 89825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 89835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8984c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlisstatic bool ValidateDependencies(const layer_data *dev_data, FRAMEBUFFER_STATE const *framebuffer, 8985127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis RENDER_PASS_STATE const *renderPass) { 8986e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool skip_call = false; 8987fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes auto const pFramebufferInfo = framebuffer->createInfo.ptr(); 8988fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes auto const pCreateInfo = renderPass->createInfo.ptr(); 8989bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto const &subpass_to_node = renderPass->subpassToNode; 89905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::vector<std::vector<uint32_t>> output_attachment_to_subpass(pCreateInfo->attachmentCount); 89915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::vector<std::vector<uint32_t>> input_attachment_to_subpass(pCreateInfo->attachmentCount); 89925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::vector<std::vector<uint32_t>> overlapping_attachments(pCreateInfo->attachmentCount); 89935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Find overlapping attachments 89945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) { 89955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t j = i + 1; j < pCreateInfo->attachmentCount; ++j) { 89965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkImageView viewi = pFramebufferInfo->pAttachments[i]; 89975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkImageView viewj = pFramebufferInfo->pAttachments[j]; 89985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (viewi == viewj) { 89995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis overlapping_attachments[i].push_back(j); 90005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis overlapping_attachments[j].push_back(i); 90015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis continue; 90025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 90039a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto view_state_i = GetImageViewState(dev_data, viewi); 90049a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto view_state_j = GetImageViewState(dev_data, viewj); 900579fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis if (!view_state_i || !view_state_j) { 90065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis continue; 90075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 900879fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis auto view_ci_i = view_state_i->create_info; 900979fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis auto view_ci_j = view_state_j->create_info; 901079fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis if (view_ci_i.image == view_ci_j.image && isRegionOverlapping(view_ci_i.subresourceRange, view_ci_j.subresourceRange)) { 90115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis overlapping_attachments[i].push_back(j); 90125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis overlapping_attachments[j].push_back(i); 90135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis continue; 90145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 90159a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_data_i = GetImageState(dev_data, view_ci_i.image); 90169a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_data_j = GetImageState(dev_data, view_ci_j.image); 90176d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis if (!image_data_i || !image_data_j) { 90185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis continue; 90195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9020e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis if (image_data_i->binding.mem == image_data_j->binding.mem && 9021e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis isRangeOverlapping(image_data_i->binding.offset, image_data_i->binding.size, image_data_j->binding.offset, 9022e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis image_data_j->binding.size)) { 90235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis overlapping_attachments[i].push_back(j); 90245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis overlapping_attachments[j].push_back(i); 90255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 90265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 90275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 90285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < overlapping_attachments.size(); ++i) { 90295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t attachment = i; 90305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto other_attachment : overlapping_attachments[i]) { 90315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!(pCreateInfo->pAttachments[attachment].flags & VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT)) { 90329bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 9033cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, VALIDATION_ERROR_00324, "DS", 9034cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Attachment %d aliases attachment %d but doesn't " 9035cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "set VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT. %s", 90369bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt attachment, other_attachment, validation_error_map[VALIDATION_ERROR_00324]); 90375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 90385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!(pCreateInfo->pAttachments[other_attachment].flags & VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT)) { 90399bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 9040cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, VALIDATION_ERROR_00324, "DS", 9041cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Attachment %d aliases attachment %d but doesn't " 9042cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "set VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT. %s", 90439bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt other_attachment, attachment, validation_error_map[VALIDATION_ERROR_00324]); 90445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 90455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 90465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 90475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Find for each attachment the subpasses that use them. 90481c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young unordered_set<uint32_t> attachmentIndices; 90495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) { 90505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i]; 90511c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young attachmentIndices.clear(); 90525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) { 90535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t attachment = subpass.pInputAttachments[j].attachment; 9054cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (attachment == VK_ATTACHMENT_UNUSED) continue; 90555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis input_attachment_to_subpass[attachment].push_back(i); 90565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto overlapping_attachment : overlapping_attachments[attachment]) { 90575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis input_attachment_to_subpass[overlapping_attachment].push_back(i); 90585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 90595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 90605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) { 90615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t attachment = subpass.pColorAttachments[j].attachment; 9062cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (attachment == VK_ATTACHMENT_UNUSED) continue; 90635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis output_attachment_to_subpass[attachment].push_back(i); 90645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto overlapping_attachment : overlapping_attachments[attachment]) { 90655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis output_attachment_to_subpass[overlapping_attachment].push_back(i); 90665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 90671c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young attachmentIndices.insert(attachment); 90685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 90695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) { 90705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t attachment = subpass.pDepthStencilAttachment->attachment; 90715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis output_attachment_to_subpass[attachment].push_back(i); 90725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto overlapping_attachment : overlapping_attachments[attachment]) { 90735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis output_attachment_to_subpass[overlapping_attachment].push_back(i); 90745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 90751c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young 90761c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young if (attachmentIndices.count(attachment)) { 90771c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young skip_call |= 90788860b85a52096f9f9b28616bc37feed505497a54Chris Forbes log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 90798860b85a52096f9f9b28616bc37feed505497a54Chris Forbes DRAWSTATE_INVALID_RENDERPASS, "DS", 90808860b85a52096f9f9b28616bc37feed505497a54Chris Forbes "Cannot use same attachment (%u) as both color and depth output in same subpass (%u).", attachment, i); 90811c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young } 90825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 90835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 90845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // If there is a dependency needed make sure one exists 90855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) { 90865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i]; 90875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // If the attachment is an input then all subpasses that output must have a dependency relationship 90885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) { 908993fe72ec8460857bdb3c101095e6eb96d6171341Chris Forbes uint32_t attachment = subpass.pInputAttachments[j].attachment; 9090cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (attachment == VK_ATTACHMENT_UNUSED) continue; 90918860b85a52096f9f9b28616bc37feed505497a54Chris Forbes CheckDependencyExists(dev_data, i, output_attachment_to_subpass[attachment], subpass_to_node, skip_call); 90925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 90935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // If the attachment is an output then all subpasses that use the attachment must have a dependency relationship 90945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) { 909593fe72ec8460857bdb3c101095e6eb96d6171341Chris Forbes uint32_t attachment = subpass.pColorAttachments[j].attachment; 9096cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (attachment == VK_ATTACHMENT_UNUSED) continue; 90978860b85a52096f9f9b28616bc37feed505497a54Chris Forbes CheckDependencyExists(dev_data, i, output_attachment_to_subpass[attachment], subpass_to_node, skip_call); 90988860b85a52096f9f9b28616bc37feed505497a54Chris Forbes CheckDependencyExists(dev_data, i, input_attachment_to_subpass[attachment], subpass_to_node, skip_call); 90995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 91005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) { 91015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const uint32_t &attachment = subpass.pDepthStencilAttachment->attachment; 91028860b85a52096f9f9b28616bc37feed505497a54Chris Forbes CheckDependencyExists(dev_data, i, output_attachment_to_subpass[attachment], subpass_to_node, skip_call); 91038860b85a52096f9f9b28616bc37feed505497a54Chris Forbes CheckDependencyExists(dev_data, i, input_attachment_to_subpass[attachment], subpass_to_node, skip_call); 91045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 91055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 91065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Loop through implicit dependencies, if this pass reads make sure the attachment is preserved for all passes after it was 91075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // written. 91085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) { 91095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i]; 91105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) { 91118860b85a52096f9f9b28616bc37feed505497a54Chris Forbes CheckPreserved(dev_data, pCreateInfo, i, subpass.pInputAttachments[j].attachment, subpass_to_node, 0, skip_call); 91125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 91135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 91145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return skip_call; 91155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 91165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 91178860b85a52096f9f9b28616bc37feed505497a54Chris Forbesstatic bool CreatePassDAG(const layer_data *dev_data, VkDevice device, const VkRenderPassCreateInfo *pCreateInfo, 9118e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves std::vector<DAGNode> &subpass_to_node, std::vector<bool> &has_self_dependency) { 9119e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool skip_call = false; 91205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) { 91215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis DAGNode &subpass_node = subpass_to_node[i]; 91225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis subpass_node.pass = i; 91235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 91245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->dependencyCount; ++i) { 91255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkSubpassDependency &dependency = pCreateInfo->pDependencies[i]; 912666a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes if (dependency.srcSubpass == VK_SUBPASS_EXTERNAL || dependency.dstSubpass == VK_SUBPASS_EXTERNAL) { 912766a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes if (dependency.srcSubpass == dependency.dstSubpass) { 912866a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes skip_call |= 91298860b85a52096f9f9b28616bc37feed505497a54Chris Forbes log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 913066a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes DRAWSTATE_INVALID_RENDERPASS, "DS", "The src and dest subpasses cannot both be external."); 913166a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes } 913266a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes } else if (dependency.srcSubpass > dependency.dstSubpass) { 91338860b85a52096f9f9b28616bc37feed505497a54Chris Forbes skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 91345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis DRAWSTATE_INVALID_RENDERPASS, "DS", 91355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis "Depedency graph must be specified such that an earlier pass cannot depend on a later pass."); 91365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (dependency.srcSubpass == dependency.dstSubpass) { 91375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis has_self_dependency[dependency.srcSubpass] = true; 91385c6aacf95832467d52b2fde1130b04bef559573aChris Forbes } else { 91395c6aacf95832467d52b2fde1130b04bef559573aChris Forbes subpass_to_node[dependency.dstSubpass].prev.push_back(dependency.srcSubpass); 91405c6aacf95832467d52b2fde1130b04bef559573aChris Forbes subpass_to_node[dependency.srcSubpass].next.push_back(dependency.dstSubpass); 91415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 91425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 91435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return skip_call; 91445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 9145918c283ac4f8c604b79abd0c8b5706d2a7352a34Chris Forbes 914689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo *pCreateInfo, 9147bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkShaderModule *pShaderModule) { 914856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 9149e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool skip_call = false; 9150c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski spv_result_t spv_valid = SPV_SUCCESS; 9151b1f65702539fd041337fccd493dc6d38dd2a603eChris Forbes 9152e3443707b0f51ba7c6c458c5039dd3004c38b73eMark Lobodzinski if (!GetDisables(dev_data)->shader_validation) { 9153e3443707b0f51ba7c6c458c5039dd3004c38b73eMark Lobodzinski // Use SPIRV-Tools validator to try and catch any issues with the module itself 9154e3443707b0f51ba7c6c458c5039dd3004c38b73eMark Lobodzinski spv_context ctx = spvContextCreate(SPV_ENV_VULKAN_1_0); 9155e3443707b0f51ba7c6c458c5039dd3004c38b73eMark Lobodzinski spv_const_binary_t binary{pCreateInfo->pCode, pCreateInfo->codeSize / sizeof(uint32_t)}; 9156e3443707b0f51ba7c6c458c5039dd3004c38b73eMark Lobodzinski spv_diagnostic diag = nullptr; 9157b1f65702539fd041337fccd493dc6d38dd2a603eChris Forbes 9158c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski spv_valid = spvValidate(ctx, &binary, &diag); 9159c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski if (spv_valid != SPV_SUCCESS) { 91605581a92674a04d2ef49fde417e657f64e3aeed69Mark Lobodzinski if (!dev_data->device_extensions.nv_glsl_shader_enabled || (pCreateInfo->pCode[0] == spv::MagicNumber)) { 9161c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski skip_call |= log_msg(dev_data->report_data, 9162c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski spv_valid == SPV_WARNING ? VK_DEBUG_REPORT_WARNING_BIT_EXT : VK_DEBUG_REPORT_ERROR_BIT_EXT, 9163c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski VkDebugReportObjectTypeEXT(0), 0, __LINE__, SHADER_CHECKER_INCONSISTENT_SPIRV, "SC", 9164c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski "SPIR-V module not valid: %s", diag && diag->error ? diag->error : "(no error text)"); 9165c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski } 9166e3443707b0f51ba7c6c458c5039dd3004c38b73eMark Lobodzinski } 91675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9168e3443707b0f51ba7c6c458c5039dd3004c38b73eMark Lobodzinski spvDiagnosticDestroy(diag); 9169e3443707b0f51ba7c6c458c5039dd3004c38b73eMark Lobodzinski spvContextDestroy(ctx); 9170b1f65702539fd041337fccd493dc6d38dd2a603eChris Forbes 9171e3443707b0f51ba7c6c458c5039dd3004c38b73eMark Lobodzinski if (skip_call) return VK_ERROR_VALIDATION_FAILED_EXT; 9172e3443707b0f51ba7c6c458c5039dd3004c38b73eMark Lobodzinski } 91735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 91744a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult res = dev_data->dispatch_table.CreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule); 91755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9176e3443707b0f51ba7c6c458c5039dd3004c38b73eMark Lobodzinski if (res == VK_SUCCESS && !GetDisables(dev_data)->shader_validation) { 9177b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 9178c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski const auto new_shader_module = (SPV_SUCCESS == spv_valid ? new shader_module(pCreateInfo) : new shader_module()); 9179c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski dev_data->shaderModuleMap[*pShaderModule] = unique_ptr<shader_module>(new_shader_module); 91805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 91815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return res; 91825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 91835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 91844f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinskistatic bool ValidateAttachmentIndex(layer_data *dev_data, uint32_t attachment, uint32_t attachment_count, const char *type) { 91854f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski bool skip_call = false; 91864f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski if (attachment >= attachment_count && attachment != VK_ATTACHMENT_UNUSED) { 91874f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 9188e52ca7be57745459d6aa4903a3880fc8eaa9d3dcChris Forbes VALIDATION_ERROR_00325, "DS", 9189bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "CreateRenderPass: %s attachment %d must be less than the total number of attachments %d. %s", type, 9190bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski attachment, attachment_count, validation_error_map[VALIDATION_ERROR_00325]); 91914f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 91924f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski return skip_call; 91934f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski} 91944f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski 9195bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic bool IsPowerOfTwo(unsigned x) { return x && !(x & (x - 1)); } 9196805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes 91974f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinskistatic bool ValidateRenderpassAttachmentUsage(layer_data *dev_data, const VkRenderPassCreateInfo *pCreateInfo) { 91984f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski bool skip_call = false; 91994f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) { 92004f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i]; 92014f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski if (subpass.pipelineBindPoint != VK_PIPELINE_BIND_POINT_GRAPHICS) { 92029bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 92039bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt VALIDATION_ERROR_00347, "DS", 92049bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "CreateRenderPass: Pipeline bind point for subpass %d must be VK_PIPELINE_BIND_POINT_GRAPHICS. %s", 92059bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt i, validation_error_map[VALIDATION_ERROR_00347]); 92064f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 92074f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski for (uint32_t j = 0; j < subpass.preserveAttachmentCount; ++j) { 92084f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski uint32_t attachment = subpass.pPreserveAttachments[j]; 92094f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski if (attachment == VK_ATTACHMENT_UNUSED) { 92104f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 92119bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt __LINE__, VALIDATION_ERROR_00356, "DS", 92129bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "CreateRenderPass: Preserve attachment (%d) must not be VK_ATTACHMENT_UNUSED. %s", j, 92139bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt validation_error_map[VALIDATION_ERROR_00356]); 92144f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } else { 92154f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski skip_call |= ValidateAttachmentIndex(dev_data, attachment, pCreateInfo->attachmentCount, "Preserve"); 92164f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 92174f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 92186a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes 9219bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto subpass_performs_resolve = 9220bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski subpass.pResolveAttachments && 9221bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski std::any_of(subpass.pResolveAttachments, subpass.pResolveAttachments + subpass.colorAttachmentCount, 9222bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski [](VkAttachmentReference ref) { return ref.attachment != VK_ATTACHMENT_UNUSED; }); 92236a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes 9224805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes unsigned sample_count = 0; 9225805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes 92264f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) { 92274f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski uint32_t attachment; 92284f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski if (subpass.pResolveAttachments) { 92294f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski attachment = subpass.pResolveAttachments[j].attachment; 92304f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski skip_call |= ValidateAttachmentIndex(dev_data, attachment, pCreateInfo->attachmentCount, "Resolve"); 92316a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes 92326a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes if (!skip_call && attachment != VK_ATTACHMENT_UNUSED && 92336a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes pCreateInfo->pAttachments[attachment].samples != VK_SAMPLE_COUNT_1_BIT) { 92346a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, 92359bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt __LINE__, VALIDATION_ERROR_00352, "DS", 92366a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes "CreateRenderPass: Subpass %u requests multisample resolve into attachment %u, " 92379bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "which must have VK_SAMPLE_COUNT_1_BIT but has %s. %s", 92389bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt i, attachment, string_VkSampleCountFlagBits(pCreateInfo->pAttachments[attachment].samples), 92399bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt validation_error_map[VALIDATION_ERROR_00352]); 92406a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes } 92414f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 92424f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski attachment = subpass.pColorAttachments[j].attachment; 92434f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski skip_call |= ValidateAttachmentIndex(dev_data, attachment, pCreateInfo->attachmentCount, "Color"); 92446a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes 9245805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes if (!skip_call && attachment != VK_ATTACHMENT_UNUSED) { 9246805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes sample_count |= (unsigned)pCreateInfo->pAttachments[attachment].samples; 9247805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes 9248bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (subpass_performs_resolve && pCreateInfo->pAttachments[attachment].samples == VK_SAMPLE_COUNT_1_BIT) { 9249dc7c45f01ae5690f7c969b4760463c1a6bac52d5Chris Forbes skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, 92509bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt __LINE__, VALIDATION_ERROR_00351, "DS", 9251dc7c45f01ae5690f7c969b4760463c1a6bac52d5Chris Forbes "CreateRenderPass: Subpass %u requests multisample resolve from attachment %u " 92529bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "which has VK_SAMPLE_COUNT_1_BIT. %s", 92539bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt i, attachment, validation_error_map[VALIDATION_ERROR_00351]); 9254dc7c45f01ae5690f7c969b4760463c1a6bac52d5Chris Forbes } 92556a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes } 92564f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 9257dc7c45f01ae5690f7c969b4760463c1a6bac52d5Chris Forbes 92584f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) { 92594f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski uint32_t attachment = subpass.pDepthStencilAttachment->attachment; 92604f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski skip_call |= ValidateAttachmentIndex(dev_data, attachment, pCreateInfo->attachmentCount, "Depth stencil"); 9261805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes 9262805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes if (!skip_call && attachment != VK_ATTACHMENT_UNUSED) { 9263805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes sample_count |= (unsigned)pCreateInfo->pAttachments[attachment].samples; 9264805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes } 92654f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 9266dc7c45f01ae5690f7c969b4760463c1a6bac52d5Chris Forbes 92674f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) { 92684f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski uint32_t attachment = subpass.pInputAttachments[j].attachment; 92694f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski skip_call |= ValidateAttachmentIndex(dev_data, attachment, pCreateInfo->attachmentCount, "Input"); 92704f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 9271805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes 9272805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes if (sample_count && !IsPowerOfTwo(sample_count)) { 92739bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 9274cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VALIDATION_ERROR_00337, "DS", 9275cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "CreateRenderPass: Subpass %u attempts to render to " 9276cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "attachments with inconsistent sample counts. %s", 92779bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt i, validation_error_map[VALIDATION_ERROR_00337]); 9278805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes } 92794f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 92804f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski return skip_call; 92814f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski} 92824f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski 928389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateRenderPass(VkDevice device, const VkRenderPassCreateInfo *pCreateInfo, 92844f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass) { 9285e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool skip_call = false; 928656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 92874f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski 92884f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski std::unique_lock<std::mutex> lock(global_lock); 92894f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski // TODO: As part of wrapping up the mem_tracker/core_validation merge the following routine should be consolidated with 92904f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski // ValidateLayouts. 92914f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski skip_call |= ValidateRenderpassAttachmentUsage(dev_data, pCreateInfo); 9292208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->dependencyCount; ++i) { 9293208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis skip_call |= ValidateStageMaskGsTsEnables(dev_data, pCreateInfo->pDependencies[i].srcStageMask, "vkCreateRenderPass()", 9294208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis VALIDATION_ERROR_00368, VALIDATION_ERROR_00370); 9295208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis skip_call |= ValidateStageMaskGsTsEnables(dev_data, pCreateInfo->pDependencies[i].dstStageMask, "vkCreateRenderPass()", 9296208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis VALIDATION_ERROR_00369, VALIDATION_ERROR_00371); 9297208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis } 9298ab38df28c5ae1816c5fa33c0c7840c6950e83f0dChris Forbes if (!skip_call) { 9299ab38df28c5ae1816c5fa33c0c7840c6950e83f0dChris Forbes skip_call |= ValidateLayouts(dev_data, device, pCreateInfo); 9300ab38df28c5ae1816c5fa33c0c7840c6950e83f0dChris Forbes } 9301ff6101de02d1677fb54962e2ff57875e76898e26Chris Forbes lock.unlock(); 93024f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski 93034f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski if (skip_call) { 93044f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski return VK_ERROR_VALIDATION_FAILED_EXT; 93054f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 93064f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski 93074a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateRenderPass(device, pCreateInfo, pAllocator, pRenderPass); 9308ff6101de02d1677fb54962e2ff57875e76898e26Chris Forbes 93095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 93104f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski lock.lock(); 93114f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski 93124f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski std::vector<bool> has_self_dependency(pCreateInfo->subpassCount); 93134f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski std::vector<DAGNode> subpass_to_node(pCreateInfo->subpassCount); 93144f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski skip_call |= CreatePassDAG(dev_data, device, pCreateInfo, subpass_to_node, has_self_dependency); 93154f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski 9316127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis auto render_pass = unique_ptr<RENDER_PASS_STATE>(new RENDER_PASS_STATE(pCreateInfo)); 931798cddf7090b5d5dcc382045867753ef703d1c3d3Chris Forbes render_pass->renderPass = *pRenderPass; 9318cf2686cdbb12af8a29ca598c126b5e37215f0ef7Chris Forbes render_pass->hasSelfDependency = has_self_dependency; 9319cf2686cdbb12af8a29ca598c126b5e37215f0ef7Chris Forbes render_pass->subpassToNode = subpass_to_node; 9320db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes 932187e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis // TODO: Maybe fill list and then copy instead of locking 9322cf2686cdbb12af8a29ca598c126b5e37215f0ef7Chris Forbes std::unordered_map<uint32_t, bool> &attachment_first_read = render_pass->attachment_first_read; 93236600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski std::unordered_map<uint32_t, VkImageLayout> &attachment_first_layout = render_pass->attachment_first_layout; 932487e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) { 932587e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i]; 932687e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) { 93274f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski uint32_t attachment = subpass.pColorAttachments[j].attachment; 93284f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski if (!attachment_first_read.count(attachment)) { 93294f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski attachment_first_read.insert(std::make_pair(attachment, false)); 93304f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski attachment_first_layout.insert(std::make_pair(attachment, subpass.pColorAttachments[j].layout)); 93310d615f0a5724edac98475366cf3e486dccc1f2d6Michael Lentine } 933287e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis } 933387e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) { 933487e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis uint32_t attachment = subpass.pDepthStencilAttachment->attachment; 93354f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski if (!attachment_first_read.count(attachment)) { 93364f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski attachment_first_read.insert(std::make_pair(attachment, false)); 93374f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski attachment_first_layout.insert(std::make_pair(attachment, subpass.pDepthStencilAttachment->layout)); 933824991fb692f7e2d457da50d50c40f2705591300cMichael Lentine } 933987e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis } 9340a5ce96d7c88653668a2b33a6b72bd3cb16d73f48Michael Lentine for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) { 9341a5ce96d7c88653668a2b33a6b72bd3cb16d73f48Michael Lentine uint32_t attachment = subpass.pInputAttachments[j].attachment; 93424f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski if (!attachment_first_read.count(attachment)) { 93434f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski attachment_first_read.insert(std::make_pair(attachment, true)); 93444f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski attachment_first_layout.insert(std::make_pair(attachment, subpass.pInputAttachments[j].layout)); 934524991fb692f7e2d457da50d50c40f2705591300cMichael Lentine } 9346a5ce96d7c88653668a2b33a6b72bd3cb16d73f48Michael Lentine } 934787e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis } 9348db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes 9349fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes dev_data->renderPassMap[*pRenderPass] = std::move(render_pass); 93505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 93515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 93525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 93534f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski 93549bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardtstatic bool validatePrimaryCommandBuffer(const layer_data *dev_data, const GLOBAL_CB_NODE *pCB, const std::string &cmd_name, 93559bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt UNIQUE_VALIDATION_ERROR_CODE error_code) { 9356e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool skip_call = false; 93575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB->createInfo.level != VK_COMMAND_BUFFER_LEVEL_PRIMARY) { 93588860b85a52096f9f9b28616bc37feed505497a54Chris Forbes skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 93599bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt error_code, "DS", "Cannot execute command %s on a secondary command buffer. %s", cmd_name.c_str(), 93609bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt validation_error_map[error_code]); 93615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 93625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return skip_call; 93635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 93645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 93658860b85a52096f9f9b28616bc37feed505497a54Chris Forbesstatic bool VerifyRenderAreaBounds(const layer_data *dev_data, const VkRenderPassBeginInfo *pRenderPassBegin) { 9366885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine bool skip_call = false; 9367c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis const safe_VkFramebufferCreateInfo *pFramebufferInfo = 93689a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis &GetFramebufferState(dev_data, pRenderPassBegin->framebuffer)->createInfo; 9369885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine if (pRenderPassBegin->renderArea.offset.x < 0 || 9370885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine (pRenderPassBegin->renderArea.offset.x + pRenderPassBegin->renderArea.extent.width) > pFramebufferInfo->width || 9371885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine pRenderPassBegin->renderArea.offset.y < 0 || 9372885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine (pRenderPassBegin->renderArea.offset.y + pRenderPassBegin->renderArea.extent.height) > pFramebufferInfo->height) { 9373885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine skip_call |= static_cast<bool>(log_msg( 93748860b85a52096f9f9b28616bc37feed505497a54Chris Forbes dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 9375885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine DRAWSTATE_INVALID_RENDER_AREA, "CORE", 9376885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine "Cannot execute a render pass with renderArea not within the bound of the " 9377885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine "framebuffer. RenderArea: x %d, y %d, width %d, height %d. Framebuffer: width %d, " 9378885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine "height %d.", 9379885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine pRenderPassBegin->renderArea.offset.x, pRenderPassBegin->renderArea.offset.y, pRenderPassBegin->renderArea.extent.width, 9380885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine pRenderPassBegin->renderArea.extent.height, pFramebufferInfo->width, pFramebufferInfo->height)); 9381885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine } 9382885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine return skip_call; 9383885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine} 9384885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine 93851a65650f856376768d7b03ea2d080aaff87cacfdMark 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 93861a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski// [load|store]Op flag must be checked 93871a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski// TODO: The memory valid flag in DEVICE_MEM_INFO should probably be split to track the validity of stencil memory separately. 9388cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskitemplate <typename T> 9389cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskistatic bool FormatSpecificLoadAndStoreOpSettings(VkFormat format, T color_depth_op, T stencil_op, T op) { 9390a49b8a211ce07e7fa2225d23f8cb11f1055b418aMark Lobodzinski if (color_depth_op != op && stencil_op != op) { 9391a49b8a211ce07e7fa2225d23f8cb11f1055b418aMark Lobodzinski return false; 9392a49b8a211ce07e7fa2225d23f8cb11f1055b418aMark Lobodzinski } 93931a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski bool check_color_depth_load_op = !vk_format_is_stencil_only(format); 93941a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski bool check_stencil_load_op = vk_format_is_depth_and_stencil(format) || !check_color_depth_load_op; 9395a49b8a211ce07e7fa2225d23f8cb11f1055b418aMark Lobodzinski 9396a49b8a211ce07e7fa2225d23f8cb11f1055b418aMark Lobodzinski return (((check_color_depth_load_op == true) && (color_depth_op == op)) || 9397a49b8a211ce07e7fa2225d23f8cb11f1055b418aMark Lobodzinski ((check_stencil_load_op == true) && (stencil_op == op))); 93981a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski} 93991a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski 9400bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBeginRenderPass(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *pRenderPassBegin, 9401bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkSubpassContents contents) { 940283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 940356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 9404b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 94059a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *cb_node = GetCBNode(dev_data, commandBuffer); 94069a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto render_pass_state = pRenderPassBegin ? GetRenderPassState(dev_data, pRenderPassBegin->renderPass) : nullptr; 94079a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto framebuffer = pRenderPassBegin ? GetFramebufferState(dev_data, pRenderPassBegin->framebuffer) : nullptr; 9408f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis if (cb_node) { 9409308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski if (render_pass_state) { 9410cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski uint32_t clear_op_size = 0; // Make sure pClearValues is at least as large as last LOAD_OP_CLEAR 9411f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->activeFramebuffer = pRenderPassBegin->framebuffer; 9412308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski for (uint32_t i = 0; i < render_pass_state->createInfo.attachmentCount; ++i) { 9413f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes MT_FB_ATTACHMENT_INFO &fb_info = framebuffer->attachments[i]; 9414308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski auto pAttachment = &render_pass_state->createInfo.pAttachments[i]; 9415bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (FormatSpecificLoadAndStoreOpSettings(pAttachment->format, pAttachment->loadOp, pAttachment->stencilLoadOp, 94161a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski VK_ATTACHMENT_LOAD_OP_CLEAR)) { 941792bc0680357019834b7529148ab6d73353ce02c7Mark Lobodzinski clear_op_size = static_cast<uint32_t>(i) + 1; 941816387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes std::function<bool()> function = [=]() { 94199a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis SetImageMemoryValid(dev_data, GetImageState(dev_data, fb_info.image), true); 942016387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes return false; 942116387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes }; 9422f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->validate_functions.push_back(function); 9423db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes } else if (FormatSpecificLoadAndStoreOpSettings(pAttachment->format, pAttachment->loadOp, 9424bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pAttachment->stencilLoadOp, VK_ATTACHMENT_LOAD_OP_DONT_CARE)) { 942516387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes std::function<bool()> function = [=]() { 94269a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis SetImageMemoryValid(dev_data, GetImageState(dev_data, fb_info.image), false); 942716387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes return false; 942816387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes }; 9429f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->validate_functions.push_back(function); 9430db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes } else if (FormatSpecificLoadAndStoreOpSettings(pAttachment->format, pAttachment->loadOp, 9431bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pAttachment->stencilLoadOp, VK_ATTACHMENT_LOAD_OP_LOAD)) { 943216387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes std::function<bool()> function = [=]() { 94339a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis return ValidateImageMemoryIsValid(dev_data, GetImageState(dev_data, fb_info.image), 9434f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis "vkCmdBeginRenderPass()"); 943516387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes }; 9436f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->validate_functions.push_back(function); 943716387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes } 9438308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski if (render_pass_state->attachment_first_read[i]) { 943916387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes std::function<bool()> function = [=]() { 94409a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis return ValidateImageMemoryIsValid(dev_data, GetImageState(dev_data, fb_info.image), 9441f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis "vkCmdBeginRenderPass()"); 944216387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes }; 9443f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->validate_functions.push_back(function); 94445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 94455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 94466de3c6ffa0819ee37cd5cecee918b062145e2ff1Tobin Ehlis if (clear_op_size > pRenderPassBegin->clearValueCount) { 9447369cf6deef1fca74f9eb1f8ef6e96deba715b133Slawomir Cygan skip_call |= log_msg( 9448369cf6deef1fca74f9eb1f8ef6e96deba715b133Slawomir Cygan dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT, 9449308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski reinterpret_cast<uint64_t &>(render_pass_state->renderPass), __LINE__, VALIDATION_ERROR_00442, "DS", 9450bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "In vkCmdBeginRenderPass() the VkRenderPassBeginInfo struct has a clearValueCount of %u but there must " 9451bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "be at least %u entries in pClearValues array to account for the highest index attachment in renderPass " 9452cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "0x%" PRIx64 9453cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " that uses VK_ATTACHMENT_LOAD_OP_CLEAR is %u. Note that the pClearValues array " 9454bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "is indexed by attachment number so even if some pClearValues entries between 0 and %u correspond to " 9455bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "attachments that aren't cleared they will be ignored. %s", 9456308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski pRenderPassBegin->clearValueCount, clear_op_size, reinterpret_cast<uint64_t &>(render_pass_state->renderPass), 94575504d0369cbc97ad7c221eddbad439bfb83e3fb6Mark Lobodzinski clear_op_size, clear_op_size - 1, validation_error_map[VALIDATION_ERROR_00442]); 9458369cf6deef1fca74f9eb1f8ef6e96deba715b133Slawomir Cygan } 9459369cf6deef1fca74f9eb1f8ef6e96deba715b133Slawomir Cygan if (clear_op_size < pRenderPassBegin->clearValueCount) { 9460369cf6deef1fca74f9eb1f8ef6e96deba715b133Slawomir Cygan skip_call |= log_msg( 9461369cf6deef1fca74f9eb1f8ef6e96deba715b133Slawomir Cygan dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT, 9462308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski reinterpret_cast<uint64_t &>(render_pass_state->renderPass), __LINE__, 9463308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski DRAWSTATE_RENDERPASS_TOO_MANY_CLEAR_VALUES, "DS", 9464369cf6deef1fca74f9eb1f8ef6e96deba715b133Slawomir Cygan "In vkCmdBeginRenderPass() the VkRenderPassBeginInfo struct has a clearValueCount of %u but only first %u " 94657bab3d8f0599701f6e26a2d76314588486ae99c9Mark Lobodzinski "entries in pClearValues array are used. The highest index of any attachment in renderPass 0x%" PRIx64 9466369cf6deef1fca74f9eb1f8ef6e96deba715b133Slawomir Cygan " that uses VK_ATTACHMENT_LOAD_OP_CLEAR is %u - other pClearValues are ignored.", 9467308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski pRenderPassBegin->clearValueCount, clear_op_size, reinterpret_cast<uint64_t &>(render_pass_state->renderPass), 94687bab3d8f0599701f6e26a2d76314588486ae99c9Mark Lobodzinski clear_op_size - 1); 94693d71bca42a843966040d6ada9c029e0ec9f35ca6Tobin Ehlis } 947083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= VerifyRenderAreaBounds(dev_data, pRenderPassBegin); 947155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski skip_call |= VerifyFramebufferAndRenderPassLayouts(dev_data, cb_node, pRenderPassBegin, 94729a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GetFramebufferState(dev_data, pRenderPassBegin->framebuffer)); 9473ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen skip_call |= insideRenderPass(dev_data, cb_node, "vkCmdBeginRenderPass()", VALIDATION_ERROR_00440); 9474308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski skip_call |= ValidateDependencies(dev_data, framebuffer, render_pass_state); 94759bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt skip_call |= validatePrimaryCommandBuffer(dev_data, cb_node, "vkCmdBeginRenderPass", VALIDATION_ERROR_00441); 947629f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, cb_node, CMD_BEGINRENDERPASS, "vkCmdBeginRenderPass()"); 94771ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(cb_node, CMD_BEGINRENDERPASS); 9478308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski cb_node->activeRenderPass = render_pass_state; 94795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // This is a shallow copy as that is all that is needed for now 9480f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->activeRenderPassBeginInfo = *pRenderPassBegin; 9481f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->activeSubpass = 0; 9482f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->activeSubpassContents = contents; 9483f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->framebuffers.insert(pRenderPassBegin->framebuffer); 9484883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis // Connect this framebuffer and its children to this cmdBuffer 9485883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis AddFramebufferBinding(dev_data, cb_node, framebuffer); 9486ea0f86230ff5c52f805ac831a1ed5a92bd123368Chris Forbes // transition attachments to the correct layouts for the first subpass 948755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski TransitionSubpassLayouts(dev_data, cb_node, &cb_node->activeRenderPassBeginInfo, cb_node->activeSubpass, framebuffer); 94885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 94895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9490b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 949183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis if (!skip_call) { 94924a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdBeginRenderPass(commandBuffer, pRenderPassBegin, contents); 94935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 94945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 94955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 949689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents) { 949783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 949856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 9499b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 95009a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 95015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 95029bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt skip_call |= validatePrimaryCommandBuffer(dev_data, pCB, "vkCmdNextSubpass", VALIDATION_ERROR_00459); 950329f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_NEXTSUBPASS, "vkCmdNextSubpass()"); 95041ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_NEXTSUBPASS); 9505ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen skip_call |= outsideRenderPass(dev_data, pCB, "vkCmdNextSubpass()", VALIDATION_ERROR_00458); 950680281691386b37385846f21b38e8c9d4b12cc74eChris Forbes 9507fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes auto subpassCount = pCB->activeRenderPass->createInfo.subpassCount; 950880281691386b37385846f21b38e8c9d4b12cc74eChris Forbes if (pCB->activeSubpass == subpassCount - 1) { 95099bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt skip_call |= log_msg( 95109bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 95119bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt reinterpret_cast<uint64_t>(commandBuffer), __LINE__, VALIDATION_ERROR_00453, "DS", 95129bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "vkCmdNextSubpass(): Attempted to advance beyond final subpass. %s", validation_error_map[VALIDATION_ERROR_00453]); 951380281691386b37385846f21b38e8c9d4b12cc74eChris Forbes } 95145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9515b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 951696ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes 9517cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip_call) return; 951896ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes 95194a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdNextSubpass(commandBuffer, contents); 952096ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes 952196ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes if (pCB) { 9522bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski lock.lock(); 9523bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pCB->activeSubpass++; 9524bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pCB->activeSubpassContents = contents; 952555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski TransitionSubpassLayouts(dev_data, pCB, &pCB->activeRenderPassBeginInfo, pCB->activeSubpass, 95269a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GetFramebufferState(dev_data, pCB->activeRenderPassBeginInfo.framebuffer)); 952796ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes } 95285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 95295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 953089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdEndRenderPass(VkCommandBuffer commandBuffer) { 953183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 953256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 9533b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 95349a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pCB = GetCBNode(dev_data, commandBuffer); 953555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski FRAMEBUFFER_STATE *framebuffer = NULL; 953658c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes if (pCB) { 9537127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis RENDER_PASS_STATE *rp_state = pCB->activeRenderPass; 95389a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis framebuffer = GetFramebufferState(dev_data, pCB->activeFramebuffer); 9539127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis if (rp_state) { 9540127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis if (pCB->activeSubpass != rp_state->createInfo.subpassCount - 1) { 95419bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt skip_call |= log_msg( 95429bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 95439bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt reinterpret_cast<uint64_t>(commandBuffer), __LINE__, VALIDATION_ERROR_00460, "DS", 95449bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "vkCmdEndRenderPass(): Called before reaching final subpass. %s", validation_error_map[VALIDATION_ERROR_00460]); 954502a3382f28fc7c6ec6018165be88aa6fc4f05c9eChris Forbes } 954602a3382f28fc7c6ec6018165be88aa6fc4f05c9eChris Forbes 9547127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis for (size_t i = 0; i < rp_state->createInfo.attachmentCount; ++i) { 9548e3ad4b1284408353cc56a04951c1df1f35a636ceChris Forbes MT_FB_ATTACHMENT_INFO &fb_info = framebuffer->attachments[i]; 9549127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis auto pAttachment = &rp_state->createInfo.pAttachments[i]; 9550bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (FormatSpecificLoadAndStoreOpSettings(pAttachment->format, pAttachment->storeOp, pAttachment->stencilStoreOp, 9551bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VK_ATTACHMENT_STORE_OP_STORE)) { 955258c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes std::function<bool()> function = [=]() { 95539a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis SetImageMemoryValid(dev_data, GetImageState(dev_data, fb_info.image), true); 955458c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes return false; 955558c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes }; 955658c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes pCB->validate_functions.push_back(function); 9557db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes } else if (FormatSpecificLoadAndStoreOpSettings(pAttachment->format, pAttachment->storeOp, 9558bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pAttachment->stencilStoreOp, VK_ATTACHMENT_STORE_OP_DONT_CARE)) { 955958c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes std::function<bool()> function = [=]() { 95609a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis SetImageMemoryValid(dev_data, GetImageState(dev_data, fb_info.image), false); 956158c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes return false; 956258c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes }; 956358c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes pCB->validate_functions.push_back(function); 95645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 95655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 95665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9567ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen skip_call |= outsideRenderPass(dev_data, pCB, "vkCmdEndRenderpass()", VALIDATION_ERROR_00464); 95689bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt skip_call |= validatePrimaryCommandBuffer(dev_data, pCB, "vkCmdEndRenderPass", VALIDATION_ERROR_00465); 956929f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_ENDRENDERPASS, "vkCmdEndRenderPass()"); 95701ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_ENDRENDERPASS); 95710e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes } 95720e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes lock.unlock(); 95730e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes 9574cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip_call) return; 95750e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes 95764a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdEndRenderPass(commandBuffer); 95770e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes 95780e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes if (pCB) { 95790e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes lock.lock(); 958055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski TransitionFinalSubpassLayouts(dev_data, pCB, &pCB->activeRenderPassBeginInfo, framebuffer); 958158c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes pCB->activeRenderPass = nullptr; 958258c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes pCB->activeSubpass = 0; 958358c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes pCB->activeFramebuffer = VK_NULL_HANDLE; 95845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 95855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 95865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9587a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlisstatic bool logInvalidAttachmentMessage(layer_data *dev_data, VkCommandBuffer secondaryBuffer, uint32_t primaryAttach, 9588a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis uint32_t secondaryAttach, const char *msg) { 95895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 9590cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VALIDATION_ERROR_02059, "DS", "vkCmdExecuteCommands() called w/ invalid Secondary Cmd Buffer 0x%" PRIx64 9591cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " which has a render pass " 9592cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "that is not compatible with the Primary Cmd Buffer current render pass. " 9593cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Attachment %u is not compatible with %u: %s. %s", 95949bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt reinterpret_cast<uint64_t &>(secondaryBuffer), primaryAttach, secondaryAttach, msg, 95959bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt validation_error_map[VALIDATION_ERROR_02059]); 95965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 95975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9598a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlisstatic bool validateAttachmentCompatibility(layer_data *dev_data, VkCommandBuffer primaryBuffer, 9599a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis VkRenderPassCreateInfo const *primaryPassCI, uint32_t primaryAttach, 9600a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis VkCommandBuffer secondaryBuffer, VkRenderPassCreateInfo const *secondaryPassCI, 9601e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves uint32_t secondaryAttach, bool is_multi) { 96025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool skip_call = false; 9603a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis if (primaryPassCI->attachmentCount <= primaryAttach) { 96045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis primaryAttach = VK_ATTACHMENT_UNUSED; 96055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9606a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis if (secondaryPassCI->attachmentCount <= secondaryAttach) { 96075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis secondaryAttach = VK_ATTACHMENT_UNUSED; 96085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 96095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (primaryAttach == VK_ATTACHMENT_UNUSED && secondaryAttach == VK_ATTACHMENT_UNUSED) { 96105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return skip_call; 96115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 96125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (primaryAttach == VK_ATTACHMENT_UNUSED) { 9613a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis skip_call |= logInvalidAttachmentMessage(dev_data, secondaryBuffer, primaryAttach, secondaryAttach, 9614a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis "The first is unused while the second is not."); 96155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return skip_call; 96165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 96175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (secondaryAttach == VK_ATTACHMENT_UNUSED) { 9618a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis skip_call |= logInvalidAttachmentMessage(dev_data, secondaryBuffer, primaryAttach, secondaryAttach, 9619a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis "The second is unused while the first is not."); 96205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return skip_call; 96215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9622a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis if (primaryPassCI->pAttachments[primaryAttach].format != secondaryPassCI->pAttachments[secondaryAttach].format) { 9623a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis skip_call |= 9624a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis logInvalidAttachmentMessage(dev_data, secondaryBuffer, primaryAttach, secondaryAttach, "They have different formats."); 96255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9626a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis if (primaryPassCI->pAttachments[primaryAttach].samples != secondaryPassCI->pAttachments[secondaryAttach].samples) { 9627a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis skip_call |= 9628a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis logInvalidAttachmentMessage(dev_data, secondaryBuffer, primaryAttach, secondaryAttach, "They have different samples."); 96295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9630a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis if (is_multi && primaryPassCI->pAttachments[primaryAttach].flags != secondaryPassCI->pAttachments[secondaryAttach].flags) { 9631a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis skip_call |= 9632a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis logInvalidAttachmentMessage(dev_data, secondaryBuffer, primaryAttach, secondaryAttach, "They have different flags."); 96335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 96345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return skip_call; 96355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 96365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9637a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlisstatic bool validateSubpassCompatibility(layer_data *dev_data, VkCommandBuffer primaryBuffer, 9638a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis VkRenderPassCreateInfo const *primaryPassCI, VkCommandBuffer secondaryBuffer, 9639a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis VkRenderPassCreateInfo const *secondaryPassCI, const int subpass, bool is_multi) { 96405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool skip_call = false; 9641a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis const VkSubpassDescription &primary_desc = primaryPassCI->pSubpasses[subpass]; 9642a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis const VkSubpassDescription &secondary_desc = secondaryPassCI->pSubpasses[subpass]; 96435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t maxInputAttachmentCount = std::max(primary_desc.inputAttachmentCount, secondary_desc.inputAttachmentCount); 96445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < maxInputAttachmentCount; ++i) { 96455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t primary_input_attach = VK_ATTACHMENT_UNUSED, secondary_input_attach = VK_ATTACHMENT_UNUSED; 96465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (i < primary_desc.inputAttachmentCount) { 96475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis primary_input_attach = primary_desc.pInputAttachments[i].attachment; 96485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 96495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (i < secondary_desc.inputAttachmentCount) { 96505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis secondary_input_attach = secondary_desc.pInputAttachments[i].attachment; 96515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9652a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis skip_call |= validateAttachmentCompatibility(dev_data, primaryBuffer, primaryPassCI, primary_input_attach, secondaryBuffer, 9653a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis secondaryPassCI, secondary_input_attach, is_multi); 96545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 96555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t maxColorAttachmentCount = std::max(primary_desc.colorAttachmentCount, secondary_desc.colorAttachmentCount); 96565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < maxColorAttachmentCount; ++i) { 96575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t primary_color_attach = VK_ATTACHMENT_UNUSED, secondary_color_attach = VK_ATTACHMENT_UNUSED; 96585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (i < primary_desc.colorAttachmentCount) { 96595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis primary_color_attach = primary_desc.pColorAttachments[i].attachment; 96605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 96615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (i < secondary_desc.colorAttachmentCount) { 96625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis secondary_color_attach = secondary_desc.pColorAttachments[i].attachment; 96635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9664a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis skip_call |= validateAttachmentCompatibility(dev_data, primaryBuffer, primaryPassCI, primary_color_attach, secondaryBuffer, 9665a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis secondaryPassCI, secondary_color_attach, is_multi); 96665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t primary_resolve_attach = VK_ATTACHMENT_UNUSED, secondary_resolve_attach = VK_ATTACHMENT_UNUSED; 96675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (i < primary_desc.colorAttachmentCount && primary_desc.pResolveAttachments) { 96685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis primary_resolve_attach = primary_desc.pResolveAttachments[i].attachment; 96695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 96705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (i < secondary_desc.colorAttachmentCount && secondary_desc.pResolveAttachments) { 96715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis secondary_resolve_attach = secondary_desc.pResolveAttachments[i].attachment; 96725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9673a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis skip_call |= validateAttachmentCompatibility(dev_data, primaryBuffer, primaryPassCI, primary_resolve_attach, 9674a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis secondaryBuffer, secondaryPassCI, secondary_resolve_attach, is_multi); 96755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 96765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t primary_depthstencil_attach = VK_ATTACHMENT_UNUSED, secondary_depthstencil_attach = VK_ATTACHMENT_UNUSED; 96775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (primary_desc.pDepthStencilAttachment) { 96785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis primary_depthstencil_attach = primary_desc.pDepthStencilAttachment[0].attachment; 96795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 96805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (secondary_desc.pDepthStencilAttachment) { 96815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis secondary_depthstencil_attach = secondary_desc.pDepthStencilAttachment[0].attachment; 96825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9683a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis skip_call |= validateAttachmentCompatibility(dev_data, primaryBuffer, primaryPassCI, primary_depthstencil_attach, 9684a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis secondaryBuffer, secondaryPassCI, secondary_depthstencil_attach, is_multi); 96855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return skip_call; 96865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 96875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9688a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis// Verify that given renderPass CreateInfo for primary and secondary command buffers are compatible. 9689a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis// This function deals directly with the CreateInfo, there are overloaded versions below that can take the renderPass handle and 9690a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis// will then feed into this function 9691a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlisstatic bool validateRenderPassCompatibility(layer_data *dev_data, VkCommandBuffer primaryBuffer, 9692a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis VkRenderPassCreateInfo const *primaryPassCI, VkCommandBuffer secondaryBuffer, 9693a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis VkRenderPassCreateInfo const *secondaryPassCI) { 96945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool skip_call = false; 9695a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis 9696a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis if (primaryPassCI->subpassCount != secondaryPassCI->subpassCount) { 96975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 96985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS", 9699a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis "vkCmdExecuteCommands() called w/ invalid secondary Cmd Buffer 0x%" PRIx64 9700a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis " that has a subpassCount of %u that is incompatible with the primary Cmd Buffer 0x%" PRIx64 9701a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis " that has a subpassCount of %u.", 9702a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis reinterpret_cast<uint64_t &>(secondaryBuffer), secondaryPassCI->subpassCount, 9703a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis reinterpret_cast<uint64_t &>(primaryBuffer), primaryPassCI->subpassCount); 9704a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis } else { 9705a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis for (uint32_t i = 0; i < primaryPassCI->subpassCount; ++i) { 9706a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis skip_call |= validateSubpassCompatibility(dev_data, primaryBuffer, primaryPassCI, secondaryBuffer, secondaryPassCI, i, 9707a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis primaryPassCI->subpassCount > 1); 9708a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis } 97095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 97105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return skip_call; 97115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 97125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9713e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool validateFramebuffer(layer_data *dev_data, VkCommandBuffer primaryBuffer, const GLOBAL_CB_NODE *pCB, 9714e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves VkCommandBuffer secondaryBuffer, const GLOBAL_CB_NODE *pSubCB) { 97155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool skip_call = false; 97165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!pSubCB->beginInfo.pInheritanceInfo) { 97175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return skip_call; 97185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9719c5b97dda856ff837638b3ebb7e231d5507c495a3Chris Forbes VkFramebuffer primary_fb = pCB->activeFramebuffer; 97205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkFramebuffer secondary_fb = pSubCB->beginInfo.pInheritanceInfo->framebuffer; 97215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (secondary_fb != VK_NULL_HANDLE) { 97225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (primary_fb != secondary_fb) { 97239bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt skip_call |= log_msg( 97249bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 97259bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt VALIDATION_ERROR_02060, "DS", 97269bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "vkCmdExecuteCommands() called w/ invalid secondary command buffer 0x%" PRIx64 " which has a framebuffer 0x%" PRIx64 97279bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt " that is not the same as the primary command buffer's current active framebuffer 0x%" PRIx64 ". %s", 97289bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt reinterpret_cast<uint64_t &>(secondaryBuffer), reinterpret_cast<uint64_t &>(secondary_fb), 97299bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt reinterpret_cast<uint64_t &>(primary_fb), validation_error_map[VALIDATION_ERROR_02060]); 97305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 97319a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto fb = GetFramebufferState(dev_data, secondary_fb); 9732e3ad4b1284408353cc56a04951c1df1f35a636ceChris Forbes if (!fb) { 9733bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 9734bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS", 9735bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "vkCmdExecuteCommands() called w/ invalid Cmd Buffer 0x%p " 9736bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "which has invalid framebuffer 0x%" PRIx64 ".", 9737bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski (void *)secondaryBuffer, (uint64_t)(secondary_fb)); 97385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return skip_call; 97395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 97409a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_renderpass = GetRenderPassState(dev_data, pSubCB->beginInfo.pInheritanceInfo->renderPass); 9741a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis if (cb_renderpass->renderPass != fb->createInfo.renderPass) { 9742a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis skip_call |= validateRenderPassCompatibility(dev_data, secondaryBuffer, fb->renderPassCreateInfo.ptr(), secondaryBuffer, 9743fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes cb_renderpass->createInfo.ptr()); 9744a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis } 97455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 97465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return skip_call; 97475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 97485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9749e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool validateSecondaryCommandBufferState(layer_data *dev_data, GLOBAL_CB_NODE *pCB, GLOBAL_CB_NODE *pSubCB) { 975083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 97515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unordered_set<int> activeTypes; 97525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto queryObject : pCB->activeQueries) { 97535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto queryPoolData = dev_data->queryPoolMap.find(queryObject.pool); 97545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (queryPoolData != dev_data->queryPoolMap.end()) { 97555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (queryPoolData->second.createInfo.queryType == VK_QUERY_TYPE_PIPELINE_STATISTICS && 97565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pSubCB->beginInfo.pInheritanceInfo) { 97575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkQueryPipelineStatisticFlags cmdBufStatistics = pSubCB->beginInfo.pInheritanceInfo->pipelineStatistics; 97585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if ((cmdBufStatistics & queryPoolData->second.createInfo.pipelineStatistics) != cmdBufStatistics) { 9759cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 9760cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, VALIDATION_ERROR_02065, "DS", 9761cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkCmdExecuteCommands() called w/ invalid Cmd Buffer 0x%p " 9762cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "which has invalid active query pool 0x%" PRIx64 9763cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ". Pipeline statistics is being queried so the command " 9764cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "buffer must have all bits set on the queryPool. %s", 9765cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pCB->commandBuffer, reinterpret_cast<const uint64_t &>(queryPoolData->first), 9766cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski validation_error_map[VALIDATION_ERROR_02065]); 97675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 97685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 97695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis activeTypes.insert(queryPoolData->second.createInfo.queryType); 97705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 97715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 97725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto queryObject : pSubCB->startedQueries) { 97735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto queryPoolData = dev_data->queryPoolMap.find(queryObject.pool); 97745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (queryPoolData != dev_data->queryPoolMap.end() && activeTypes.count(queryPoolData->second.createInfo.queryType)) { 9775cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 9776cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS", 9777cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkCmdExecuteCommands() called w/ invalid Cmd Buffer 0x%p " 9778cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "which has invalid active query pool 0x%" PRIx64 9779cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "of type %d but a query of that type has been started on " 9780cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "secondary Cmd Buffer 0x%p.", 9781cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pCB->commandBuffer, reinterpret_cast<const uint64_t &>(queryPoolData->first), 9782cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski queryPoolData->second.createInfo.queryType, pSubCB->commandBuffer); 97835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 97845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 97857bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski 97869a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto primary_pool = GetCommandPoolNode(dev_data, pCB->createInfo.commandPool); 97879a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto secondary_pool = GetCommandPoolNode(dev_data, pSubCB->createInfo.commandPool); 97887bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski if (primary_pool && secondary_pool && (primary_pool->queueFamilyIndex != secondary_pool->queueFamilyIndex)) { 9789226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis skip_call |= 9790226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 9791226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis reinterpret_cast<uint64_t>(pSubCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_QUEUE_FAMILY, "DS", 9792226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "vkCmdExecuteCommands(): Primary command buffer 0x%p" 9793226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis " created in queue family %d has secondary command buffer 0x%p created in queue family %d.", 9794226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis pCB->commandBuffer, primary_pool->queueFamilyIndex, pSubCB->commandBuffer, secondary_pool->queueFamilyIndex); 97957bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski } 97967bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski 979783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis return skip_call; 97985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 97995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9800bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t commandBuffersCount, 9801bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkCommandBuffer *pCommandBuffers) { 980283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 980356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 9804b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 98059a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 98065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 98075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis GLOBAL_CB_NODE *pSubCB = NULL; 98085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < commandBuffersCount; i++) { 98099a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis pSubCB = GetCBNode(dev_data, pCommandBuffers[i]); 98100a8b955c23012196339f3c10ffedc631ea0f7c58Tobin Ehlis assert(pSubCB); 98110a8b955c23012196339f3c10ffedc631ea0f7c58Tobin Ehlis if (VK_COMMAND_BUFFER_LEVEL_PRIMARY == pSubCB->createInfo.level) { 981283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 98134b6738a6adb4e813d66234defee5d18b7c84340dMike Weiblen __LINE__, VALIDATION_ERROR_00153, "DS", 981483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis "vkCmdExecuteCommands() called w/ Primary Cmd Buffer 0x%p in element %u of pCommandBuffers " 98154b6738a6adb4e813d66234defee5d18b7c84340dMike Weiblen "array. All cmd buffers in pCommandBuffers array must be secondary. %s", 9816226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis pCommandBuffers[i], i, validation_error_map[VALIDATION_ERROR_00153]); 9817cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else if (pCB->activeRenderPass) { // Secondary CB w/i RenderPass must have *CONTINUE_BIT set 98189a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto secondary_rp_state = GetRenderPassState(dev_data, pSubCB->beginInfo.pInheritanceInfo->renderPass); 98195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!(pSubCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT)) { 982083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg( 98215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 98224b6738a6adb4e813d66234defee5d18b7c84340dMike Weiblen (uint64_t)pCommandBuffers[i], __LINE__, VALIDATION_ERROR_02057, "DS", 9823414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller "vkCmdExecuteCommands(): Secondary Command Buffer (0x%p) executed within render pass (0x%" PRIxLEAST64 98244b6738a6adb4e813d66234defee5d18b7c84340dMike Weiblen ") must have had vkBeginCommandBuffer() called w/ VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT set. %s", 9825226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis pCommandBuffers[i], (uint64_t)pCB->activeRenderPass->renderPass, 98264b6738a6adb4e813d66234defee5d18b7c84340dMike Weiblen validation_error_map[VALIDATION_ERROR_02057]); 98275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 98285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Make sure render pass is compatible with parent command buffer pass if has continue 9829127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis if (pCB->activeRenderPass->renderPass != secondary_rp_state->renderPass) { 9830fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes skip_call |= 9831fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes validateRenderPassCompatibility(dev_data, commandBuffer, pCB->activeRenderPass->createInfo.ptr(), 9832127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis pCommandBuffers[i], secondary_rp_state->createInfo.ptr()); 9833a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis } 98341af6125615cd6dd9735d32e2ee8684abeff28d41Tobin Ehlis // If framebuffer for secondary CB is not NULL, then it must match active FB from primaryCB 983583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= validateFramebuffer(dev_data, commandBuffer, pCB, pCommandBuffers[i], pSubCB); 98365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 98375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis string errorString = ""; 98381af6125615cd6dd9735d32e2ee8684abeff28d41Tobin Ehlis // secondaryCB must have been created w/ RP compatible w/ primaryCB active renderpass 9839127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis if ((pCB->activeRenderPass->renderPass != secondary_rp_state->renderPass) && 9840fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes !verify_renderpass_compatibility(dev_data, pCB->activeRenderPass->createInfo.ptr(), 9841127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis secondary_rp_state->createInfo.ptr(), errorString)) { 984283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg( 98435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 98445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (uint64_t)pCommandBuffers[i], __LINE__, DRAWSTATE_RENDERPASS_INCOMPATIBLE, "DS", 9845414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller "vkCmdExecuteCommands(): Secondary Command Buffer (0x%p) w/ render pass (0x%" PRIxLEAST64 9846414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller ") is incompatible w/ primary command buffer (0x%p) w/ render pass (0x%" PRIxLEAST64 ") due to: %s", 9847226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis pCommandBuffers[i], (uint64_t)pSubCB->beginInfo.pInheritanceInfo->renderPass, commandBuffer, 9848ee691f5c5fa87aac3750454d2bca2cb582e4e817Chris Forbes (uint64_t)pCB->activeRenderPass->renderPass, errorString.c_str()); 98495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 98505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 98515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODO(mlentine): Move more logic into this method 985283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= validateSecondaryCommandBufferState(dev_data, pCB, pSubCB); 985351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour skip_call |= validateCommandBufferState(dev_data, pSubCB, "vkCmdExecuteCommands()", 0); 98545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Secondary cmdBuffers are considered pending execution starting w/ 98555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // being recorded 98565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!(pSubCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT)) { 98575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (dev_data->globalInFlightCmdBuffers.find(pSubCB->commandBuffer) != dev_data->globalInFlightCmdBuffers.end()) { 9858cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 9859cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)(pCB->commandBuffer), __LINE__, 9860cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VALIDATION_ERROR_00154, "DS", 9861cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Attempt to simultaneously execute command buffer 0x%p" 9862cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " without VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT set! %s", 9863cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pCB->commandBuffer, validation_error_map[VALIDATION_ERROR_00154]); 98645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 98655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT) { 98665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Warn that non-simultaneous secondary cmd buffer renders primary non-simultaneous 986783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg( 98685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 98695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (uint64_t)(pCommandBuffers[i]), __LINE__, DRAWSTATE_INVALID_CB_SIMULTANEOUS_USE, "DS", 9870226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "vkCmdExecuteCommands(): Secondary Command Buffer (0x%p) " 9871226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "does not have VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT set and will cause primary command buffer " 9872226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "(0x%p) to be treated as if it does not have VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT " 987383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis "set, even though it does.", 9874226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis pCommandBuffers[i], pCB->commandBuffer); 98755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->beginInfo.flags &= ~VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT; 98765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 98775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9878f71dd305f197826a61f398bff725267a20ea1d90Chris Forbes if (!pCB->activeQueries.empty() && !dev_data->enabled_features.inheritedQueries) { 9879cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski skip_call |= 9880cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 9881cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski reinterpret_cast<uint64_t>(pCommandBuffers[i]), __LINE__, VALIDATION_ERROR_02062, "DS", 9882cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkCmdExecuteCommands(): Secondary Command Buffer " 9883cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "(0x%p) cannot be submitted with a query in " 9884cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "flight and inherited queries not " 9885cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "supported on this device. %s", 9886cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pCommandBuffers[i], validation_error_map[VALIDATION_ERROR_02062]); 98875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 98888567fecbf563420f5900ade277ca68908aa87259Tobin Ehlis // Propagate layout transitions to the primary cmd buffer 98898567fecbf563420f5900ade277ca68908aa87259Tobin Ehlis for (auto ilm_entry : pSubCB->imageLayoutMap) { 989055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski SetLayout(dev_data, pCB, ilm_entry.first, ilm_entry.second); 98918567fecbf563420f5900ade277ca68908aa87259Tobin Ehlis } 98925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pSubCB->primaryCommandBuffer = pCB->commandBuffer; 98935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->secondaryCommandBuffers.insert(pSubCB->commandBuffer); 98945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->globalInFlightCmdBuffers.insert(pSubCB->commandBuffer); 9895d4ee9fdb2def1e9dc70c5627c9103e264471b8ebMichael Lentine for (auto &function : pSubCB->queryUpdates) { 9896d4ee9fdb2def1e9dc70c5627c9103e264471b8ebMichael Lentine pCB->queryUpdates.push_back(function); 9897d4ee9fdb2def1e9dc70c5627c9103e264471b8ebMichael Lentine } 98985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 98999bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt skip_call |= validatePrimaryCommandBuffer(dev_data, pCB, "vkCmdExecuteComands", VALIDATION_ERROR_00163); 990029f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_EXECUTECOMMANDS, "vkCmdExecuteComands()"); 99011ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_EXECUTECOMMANDS); 99025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9903b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 9904cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.CmdExecuteCommands(commandBuffer, commandBuffersCount, pCommandBuffers); 99055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 99065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9907bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL MapMemory(VkDevice device, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size, VkFlags flags, 9908bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski void **ppData) { 990956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 99105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9911e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool skip_call = false; 99125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 9913b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 99149a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *mem_info = GetMemObjInfo(dev_data, mem); 9915cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis if (mem_info) { 9916f541bf53dee6daf82a4c8304354eac599a884d29Tobin Ehlis // TODO : This could me more fine-grained to track just region that is valid 9917f541bf53dee6daf82a4c8304354eac599a884d29Tobin Ehlis mem_info->global_valid = true; 9918623548a271287ae55415e45e3c654ee66d4e79ffTobin Ehlis auto end_offset = (VK_WHOLE_SIZE == size) ? mem_info->alloc_info.allocationSize - 1 : offset + size - 1; 9919c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski skip_call |= ValidateMapImageLayouts(dev_data, device, mem_info, offset, end_offset); 9920cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis // TODO : Do we need to create new "bound_range" for the mapped range? 9921623548a271287ae55415e45e3c654ee66d4e79ffTobin Ehlis SetMemRangesValid(dev_data, mem_info, offset, end_offset); 9922cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis if ((dev_data->phys_dev_mem_props.memoryTypes[mem_info->alloc_info.memoryTypeIndex].propertyFlags & 9923b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0) { 99242fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen skip_call = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 99252fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen (uint64_t)mem, __LINE__, VALIDATION_ERROR_00629, "MEM", 99262fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen "Mapping Memory without VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT set: mem obj 0x%" PRIxLEAST64 ". %s", 99272fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen (uint64_t)mem, validation_error_map[VALIDATION_ERROR_00629]); 99285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 99295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9930f57fc64ac43691ad98e1713886b345465573070aTobin Ehlis skip_call |= ValidateMapMemRange(dev_data, mem, offset, size); 9931b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 99325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9933e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves if (!skip_call) { 99344a0754042cf090e131e9e769d8a3633c228625beChris Forbes result = dev_data->dispatch_table.MapMemory(device, mem, offset, size, flags, ppData); 99357c0012acb5327961b0a5191434a08e5fa788786dTobin Ehlis if (VK_SUCCESS == result) { 99367c0012acb5327961b0a5191434a08e5fa788786dTobin Ehlis lock.lock(); 9937cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis // TODO : What's the point of this range? See comment on creating new "bound_range" above, which may replace this 99387c0012acb5327961b0a5191434a08e5fa788786dTobin Ehlis storeMemRanges(dev_data, mem, offset, size); 99395f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski initializeAndTrackMemory(dev_data, mem, offset, size, ppData); 99407c0012acb5327961b0a5191434a08e5fa788786dTobin Ehlis lock.unlock(); 99417c0012acb5327961b0a5191434a08e5fa788786dTobin Ehlis } 99425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 99435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 99445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 99455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 994689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL UnmapMemory(VkDevice device, VkDeviceMemory mem) { 994756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 994883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 99495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9950b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 99518860b85a52096f9f9b28616bc37feed505497a54Chris Forbes skip_call |= deleteMemRanges(dev_data, mem); 9952b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 995383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis if (!skip_call) { 99544a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.UnmapMemory(device, mem); 99555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 99565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 99575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 99588860b85a52096f9f9b28616bc37feed505497a54Chris Forbesstatic bool validateMemoryIsMapped(layer_data *dev_data, const char *funcName, uint32_t memRangeCount, 9959e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves const VkMappedMemoryRange *pMemRanges) { 9960c7ee6f2fe100c1aacfaa0872832717c906bb8a4aMark Lobodzinski bool skip = false; 99615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < memRangeCount; ++i) { 99629a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto mem_info = GetMemObjInfo(dev_data, pMemRanges[i].memory); 996357fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis if (mem_info) { 9964f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski if (pMemRanges[i].size == VK_WHOLE_SIZE) { 9965f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski if (mem_info->mem_range.offset > pMemRanges[i].offset) { 9966cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 9967cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, (uint64_t)pMemRanges[i].memory, __LINE__, 9968cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VALIDATION_ERROR_00643, "MEM", "%s: Flush/Invalidate offset (" PRINTF_SIZE_T_SPECIFIER 9969cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ") is less than Memory Object's offset " 9970cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "(" PRINTF_SIZE_T_SPECIFIER "). %s", 9971cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski funcName, static_cast<size_t>(pMemRanges[i].offset), 9972cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski static_cast<size_t>(mem_info->mem_range.offset), validation_error_map[VALIDATION_ERROR_00643]); 9973f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski } 9974f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski } else { 9975f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski const uint64_t data_end = (mem_info->mem_range.size == VK_WHOLE_SIZE) 9976f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski ? mem_info->alloc_info.allocationSize 9977f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski : (mem_info->mem_range.offset + mem_info->mem_range.size); 9978f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski if ((mem_info->mem_range.offset > pMemRanges[i].offset) || 9979f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski (data_end < (pMemRanges[i].offset + pMemRanges[i].size))) { 9980c7ee6f2fe100c1aacfaa0872832717c906bb8a4aMark Lobodzinski skip |= 9981f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 9982f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski (uint64_t)pMemRanges[i].memory, __LINE__, VALIDATION_ERROR_00642, "MEM", 9983f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski "%s: Flush/Invalidate size or offset (" PRINTF_SIZE_T_SPECIFIER ", " PRINTF_SIZE_T_SPECIFIER 9984f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski ") exceed the Memory Object's upper-bound " 9985f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski "(" PRINTF_SIZE_T_SPECIFIER "). %s", 9986f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski funcName, static_cast<size_t>(pMemRanges[i].offset + pMemRanges[i].size), 9987f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski static_cast<size_t>(pMemRanges[i].offset), static_cast<size_t>(data_end), 9988f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski validation_error_map[VALIDATION_ERROR_00642]); 9989f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski } 99905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 99915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 99925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9993c7ee6f2fe100c1aacfaa0872832717c906bb8a4aMark Lobodzinski return skip; 99945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 99955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9996bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinskistatic bool ValidateAndCopyNoncoherentMemoryToDriver(layer_data *dev_data, uint32_t mem_range_count, 9997bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski const VkMappedMemoryRange *mem_ranges) { 9998bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski bool skip = false; 9999bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski for (uint32_t i = 0; i < mem_range_count; ++i) { 100009a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto mem_info = GetMemObjInfo(dev_data, mem_ranges[i].memory); 1000157fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis if (mem_info) { 100025f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski if (mem_info->shadow_copy) { 100035f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski VkDeviceSize size = (mem_info->mem_range.size != VK_WHOLE_SIZE) 100045f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski ? mem_info->mem_range.size 10005d8a53ade6b5501256798a8b4ec0bc14f72adc1faTobin Ehlis : (mem_info->alloc_info.allocationSize - mem_info->mem_range.offset); 100065f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski char *data = static_cast<char *>(mem_info->shadow_copy); 100075f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski for (uint64_t j = 0; j < mem_info->shadow_pad_size; ++j) { 100085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (data[j] != NoncoherentMemoryFillValue) { 10009bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 10010bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, (uint64_t)mem_ranges[i].memory, __LINE__, 10011bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski MEMTRACK_INVALID_MAP, "MEM", "Memory underflow was detected on mem obj 0x%" PRIxLEAST64, 10012bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski (uint64_t)mem_ranges[i].memory); 100135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 100145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 100155f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski for (uint64_t j = (size + mem_info->shadow_pad_size); j < (2 * mem_info->shadow_pad_size + size); ++j) { 100165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (data[j] != NoncoherentMemoryFillValue) { 10017bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 10018bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, (uint64_t)mem_ranges[i].memory, __LINE__, 10019bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski MEMTRACK_INVALID_MAP, "MEM", "Memory overflow was detected on mem obj 0x%" PRIxLEAST64, 10020bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski (uint64_t)mem_ranges[i].memory); 100215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 100225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 100235f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski memcpy(mem_info->p_driver_data, static_cast<void *>(data + mem_info->shadow_pad_size), (size_t)(size)); 100245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 100255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 100265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 10027bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski return skip; 100285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 100295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10030bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinskistatic void CopyNoncoherentMemoryFromDriver(layer_data *dev_data, uint32_t mem_range_count, const VkMappedMemoryRange *mem_ranges) { 10031bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski for (uint32_t i = 0; i < mem_range_count; ++i) { 100329a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto mem_info = GetMemObjInfo(dev_data, mem_ranges[i].memory); 100335f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski if (mem_info && mem_info->shadow_copy) { 100345f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski VkDeviceSize size = (mem_info->mem_range.size != VK_WHOLE_SIZE) 100355f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski ? mem_info->mem_range.size 100365f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski : (mem_info->alloc_info.allocationSize - mem_ranges[i].offset); 100375f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski char *data = static_cast<char *>(mem_info->shadow_copy); 100385f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski memcpy(data + mem_info->shadow_pad_size, mem_info->p_driver_data, (size_t)(size)); 100399e21e56fc23ade48efd3752d2e2729895eb90349Mark Lobodzinski } 100409e21e56fc23ade48efd3752d2e2729895eb90349Mark Lobodzinski } 100419e21e56fc23ade48efd3752d2e2729895eb90349Mark Lobodzinski} 100429e21e56fc23ade48efd3752d2e2729895eb90349Mark Lobodzinski 10043ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinskistatic bool ValidateMappedMemoryRangeDeviceLimits(layer_data *dev_data, const char *func_name, uint32_t mem_range_count, 10044ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski const VkMappedMemoryRange *mem_ranges) { 10045ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski bool skip = false; 10046ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski for (uint32_t i = 0; i < mem_range_count; ++i) { 10047ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski uint64_t atom_size = dev_data->phys_dev_properties.properties.limits.nonCoherentAtomSize; 10048ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski if (vk_safe_modulo(mem_ranges[i].offset, atom_size) != 0) { 10049ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 10050ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski __LINE__, VALIDATION_ERROR_00644, "MEM", 10051ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski "%s: Offset in pMemRanges[%d] is 0x%" PRIxLEAST64 10052ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski ", which is not a multiple of VkPhysicalDeviceLimits::nonCoherentAtomSize (0x%" PRIxLEAST64 "). %s", 10053ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski func_name, i, mem_ranges[i].offset, atom_size, validation_error_map[VALIDATION_ERROR_00644]); 10054ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski } 10055ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski if ((mem_ranges[i].size != VK_WHOLE_SIZE) && (vk_safe_modulo(mem_ranges[i].size, atom_size) != 0)) { 10056ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 10057ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski __LINE__, VALIDATION_ERROR_00645, "MEM", 10058ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski "%s: Size in pMemRanges[%d] is 0x%" PRIxLEAST64 10059ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski ", which is not a multiple of VkPhysicalDeviceLimits::nonCoherentAtomSize (0x%" PRIxLEAST64 "). %s", 10060ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski func_name, i, mem_ranges[i].size, atom_size, validation_error_map[VALIDATION_ERROR_00645]); 10061ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski } 10062ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski } 10063ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski return skip; 10064ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski} 10065ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski 1006680e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinskistatic bool PreCallValidateFlushMappedMemoryRanges(layer_data *dev_data, uint32_t mem_range_count, 1006780e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski const VkMappedMemoryRange *mem_ranges) { 1006880e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski bool skip = false; 1006980e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski std::lock_guard<std::mutex> lock(global_lock); 1007080e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski skip |= ValidateAndCopyNoncoherentMemoryToDriver(dev_data, mem_range_count, mem_ranges); 1007180e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski skip |= validateMemoryIsMapped(dev_data, "vkFlushMappedMemoryRanges", mem_range_count, mem_ranges); 1007280e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski return skip; 1007380e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski} 1007480e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski 10075bba0de708d942e9a2187158915856995db1c5a4dMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL FlushMappedMemoryRanges(VkDevice device, uint32_t memRangeCount, 10076bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski const VkMappedMemoryRange *pMemRanges) { 100775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 1007856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 100795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1008080e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski if (!PreCallValidateFlushMappedMemoryRanges(dev_data, memRangeCount, pMemRanges)) { 100814a0754042cf090e131e9e769d8a3633c228625beChris Forbes result = dev_data->dispatch_table.FlushMappedMemoryRanges(device, memRangeCount, pMemRanges); 100825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 100835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 100845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 100855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1008680e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinskistatic bool PreCallValidateInvalidateMappedMemoryRanges(layer_data *dev_data, uint32_t mem_range_count, 1008780e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski const VkMappedMemoryRange *mem_ranges) { 1008880e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski bool skip = false; 1008980e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski std::lock_guard<std::mutex> lock(global_lock); 1009080e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski skip |= validateMemoryIsMapped(dev_data, "vkInvalidateMappedMemoryRanges", mem_range_count, mem_ranges); 1009180e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski return skip; 1009280e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski} 1009380e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski 1009480e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinskistatic void PostCallRecordInvalidateMappedMemoryRanges(layer_data *dev_data, uint32_t mem_range_count, 1009580e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski const VkMappedMemoryRange *mem_ranges) { 1009680e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski std::lock_guard<std::mutex> lock(global_lock); 1009780e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski // Update our shadow copy with modified driver data 1009880e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski CopyNoncoherentMemoryFromDriver(dev_data, mem_range_count, mem_ranges); 1009980e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski} 1010080e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski 10101bba0de708d942e9a2187158915856995db1c5a4dMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL InvalidateMappedMemoryRanges(VkDevice device, uint32_t memRangeCount, 10102bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski const VkMappedMemoryRange *pMemRanges) { 101035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 1010456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 101055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1010680e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski if (!PreCallValidateInvalidateMappedMemoryRanges(dev_data, memRangeCount, pMemRanges)) { 101074a0754042cf090e131e9e769d8a3633c228625beChris Forbes result = dev_data->dispatch_table.InvalidateMappedMemoryRanges(device, memRangeCount, pMemRanges); 1010880e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski if (result == VK_SUCCESS) { 1010980e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski PostCallRecordInvalidateMappedMemoryRanges(dev_data, memRangeCount, pMemRanges); 1011080e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski } 101115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 101125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 101135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 101145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10115341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Strattonstatic bool PreCallValidateBindImageMemory(layer_data *dev_data, VkImage image, VkDeviceMemory mem, VkDeviceSize memoryOffset) { 101160109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski bool skip = false; 10117b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 10118341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton 101199a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_state = GetImageState(dev_data, image); 101201facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis if (image_state) { 1012194c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis // Track objects tied to memory 1012247aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski uint64_t image_handle = reinterpret_cast<uint64_t &>(image); 101230109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski skip = SetMemBinding(dev_data, mem, image_handle, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, "vkBindImageMemory"); 10124ff3ef1181960319d2268e82dae075726f650c553Tobin Ehlis if (!image_state->memory_requirements_checked) { 10125ff3ef1181960319d2268e82dae075726f650c553Tobin Ehlis // There's not an explicit requirement in the spec to call vkGetImageMemoryRequirements() prior to calling 10126341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton // BindImageMemory but it's implied in that memory being bound must conform with VkMemoryRequirements from 10127341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton // vkGetImageMemoryRequirements() 101280109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 101290109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski image_handle, __LINE__, DRAWSTATE_INVALID_IMAGE, "DS", 101300109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski "vkBindImageMemory(): Binding memory to image 0x%" PRIxLEAST64 101310109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski " but vkGetImageMemoryRequirements() has not been called on that image.", 101320109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski image_handle); 10133ff3ef1181960319d2268e82dae075726f650c553Tobin Ehlis // Make the call for them so we can verify the state 10134ff3ef1181960319d2268e82dae075726f650c553Tobin Ehlis lock.unlock(); 10135341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton dev_data->dispatch_table.GetImageMemoryRequirements(dev_data->device, image, &image_state->requirements); 10136ff3ef1181960319d2268e82dae075726f650c553Tobin Ehlis lock.lock(); 10137ff3ef1181960319d2268e82dae075726f650c553Tobin Ehlis } 1013847aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski 1013947aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski // Track and validate bound memory range information 101409a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto mem_info = GetMemObjInfo(dev_data, mem); 1014157fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis if (mem_info) { 101420109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski skip |= InsertImageMemoryRange(dev_data, image, mem_info, memoryOffset, image_state->requirements, 101437992c34b28dd617787f0e4d34fd023f894495edbCort Stratton image_state->createInfo.tiling == VK_IMAGE_TILING_LINEAR, "vkBindImageMemory"); 101440109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski skip |= ValidateMemoryTypes(dev_data, mem_info, image_state->requirements.memoryTypeBits, "vkBindImageMemory", 101450109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski VALIDATION_ERROR_00806); 1014647aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski } 10147341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton } 10148341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton return skip; 10149341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton} 1015047aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski 10151341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Strattonstatic void PostCallRecordBindImageMemory(layer_data *dev_data, VkImage image, VkDeviceMemory mem, VkDeviceSize memoryOffset) { 10152341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton std::unique_lock<std::mutex> lock(global_lock); 10153341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton auto image_state = GetImageState(dev_data, image); 10154341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton if (image_state) { 10155341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton image_state->binding.mem = mem; 10156341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton image_state->binding.offset = memoryOffset; 10157341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton image_state->binding.size = image_state->requirements.size; 10158341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton } 10159341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton} 10160341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton 10161341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort StrattonVKAPI_ATTR VkResult VKAPI_CALL BindImageMemory(VkDevice device, VkImage image, VkDeviceMemory mem, VkDeviceSize memoryOffset) { 10162341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 10163341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 10164341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton bool skip = PreCallValidateBindImageMemory(dev_data, image, mem, memoryOffset); 10165341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton if (!skip) { 10166341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton result = dev_data->dispatch_table.BindImageMemory(device, image, mem, memoryOffset); 10167341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton if (result == VK_SUCCESS) { 10168341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton PostCallRecordBindImageMemory(dev_data, image, mem, memoryOffset); 1016994c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis } 101705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 101715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 101725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 101735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1017489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL SetEvent(VkDevice device, VkEvent event) { 101753ee1d6057ee6c49b9dbbeb067b7fd149bdba7b5cTobin Ehlis bool skip_call = false; 101763ee1d6057ee6c49b9dbbeb067b7fd149bdba7b5cTobin Ehlis VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 1017756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 10178b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 101799a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto event_state = GetEventNode(dev_data, event); 101804710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis if (event_state) { 101814710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis event_state->needsSignaled = false; 101824710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis event_state->stageMask = VK_PIPELINE_STAGE_HOST_BIT; 101834710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis if (event_state->write_in_use) { 101843ee1d6057ee6c49b9dbbeb067b7fd149bdba7b5cTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT, 101853ee1d6057ee6c49b9dbbeb067b7fd149bdba7b5cTobin Ehlis reinterpret_cast<const uint64_t &>(event), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS", 10186414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller "Cannot call vkSetEvent() on event 0x%" PRIxLEAST64 " that is already in use by a command buffer.", 101873ee1d6057ee6c49b9dbbeb067b7fd149bdba7b5cTobin Ehlis reinterpret_cast<const uint64_t &>(event)); 101883ee1d6057ee6c49b9dbbeb067b7fd149bdba7b5cTobin Ehlis } 101893ee1d6057ee6c49b9dbbeb067b7fd149bdba7b5cTobin Ehlis } 10190b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 101916fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis // Host setting event is visible to all queues immediately so update stageMask for any queue that's seen this event 101926fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis // TODO : For correctness this needs separate fix to verify that app doesn't make incorrect assumptions about the 101936fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis // ordering of this command in relation to vkCmd[Set|Reset]Events (see GH297) 101946fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis for (auto queue_data : dev_data->queueMap) { 101956fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis auto event_entry = queue_data.second.eventToStageMap.find(event); 101966fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis if (event_entry != queue_data.second.eventToStageMap.end()) { 101976fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis event_entry->second |= VK_PIPELINE_STAGE_HOST_BIT; 101986fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis } 101996fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis } 10200cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) result = dev_data->dispatch_table.SetEvent(device, event); 102015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 102025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 102035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10204bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL QueueBindSparse(VkQueue queue, uint32_t bindInfoCount, const VkBindSparseInfo *pBindInfo, 10205bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkFence fence) { 1020656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map); 102075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 10208e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool skip_call = false; 10209b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 102109a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pFence = GetFenceNode(dev_data, fence); 102119a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pQueue = GetQueueState(dev_data, queue); 10212651d92815dfff917308137bb67aacccc4f60df86Chris Forbes 102134b38d3aa8b6be6a7f5bebb472ab439da0562824fTobin Ehlis // First verify that fence is not in use 10214651d92815dfff917308137bb67aacccc4f60df86Chris Forbes skip_call |= ValidateFenceForSubmit(dev_data, pFence); 10215651d92815dfff917308137bb67aacccc4f60df86Chris Forbes 102169867daedbf52debc77d6568162ee21e071699b80Chris Forbes if (pFence) { 102179867daedbf52debc77d6568162ee21e071699b80Chris Forbes SubmitFence(pQueue, pFence, bindInfoCount); 102184b38d3aa8b6be6a7f5bebb472ab439da0562824fTobin Ehlis } 10219651d92815dfff917308137bb67aacccc4f60df86Chris Forbes 102201344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis for (uint32_t bindIdx = 0; bindIdx < bindInfoCount; ++bindIdx) { 102211344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis const VkBindSparseInfo &bindInfo = pBindInfo[bindIdx]; 102225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Track objects tied to memory 102231344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis for (uint32_t j = 0; j < bindInfo.bufferBindCount; j++) { 102241344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis for (uint32_t k = 0; k < bindInfo.pBufferBinds[j].bindCount; k++) { 10225f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis auto sparse_binding = bindInfo.pBufferBinds[j].pBinds[k]; 10226f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis if (SetSparseMemBinding(dev_data, {sparse_binding.memory, sparse_binding.memoryOffset, sparse_binding.size}, 10227f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis (uint64_t)bindInfo.pBufferBinds[j].buffer, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, 10228f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis "vkQueueBindSparse")) 10229e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves skip_call = true; 102305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 102315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 102321344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis for (uint32_t j = 0; j < bindInfo.imageOpaqueBindCount; j++) { 102331344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis for (uint32_t k = 0; k < bindInfo.pImageOpaqueBinds[j].bindCount; k++) { 10234f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis auto sparse_binding = bindInfo.pImageOpaqueBinds[j].pBinds[k]; 10235f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis if (SetSparseMemBinding(dev_data, {sparse_binding.memory, sparse_binding.memoryOffset, sparse_binding.size}, 10236f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis (uint64_t)bindInfo.pImageOpaqueBinds[j].image, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 10237f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis "vkQueueBindSparse")) 10238e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves skip_call = true; 102395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 102405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 102411344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis for (uint32_t j = 0; j < bindInfo.imageBindCount; j++) { 102421344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis for (uint32_t k = 0; k < bindInfo.pImageBinds[j].bindCount; k++) { 10243f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis auto sparse_binding = bindInfo.pImageBinds[j].pBinds[k]; 10244f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis // TODO: This size is broken for non-opaque bindings, need to update to comprehend full sparse binding data 10245f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis VkDeviceSize size = sparse_binding.extent.depth * sparse_binding.extent.height * sparse_binding.extent.width * 4; 10246f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis if (SetSparseMemBinding(dev_data, {sparse_binding.memory, sparse_binding.memoryOffset, size}, 10247f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis (uint64_t)bindInfo.pImageBinds[j].image, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 10248f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis "vkQueueBindSparse")) 10249e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves skip_call = true; 102505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 102515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 102529867daedbf52debc77d6568162ee21e071699b80Chris Forbes 102539867daedbf52debc77d6568162ee21e071699b80Chris Forbes std::vector<SEMAPHORE_WAIT> semaphore_waits; 102549867daedbf52debc77d6568162ee21e071699b80Chris Forbes std::vector<VkSemaphore> semaphore_signals; 102551344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis for (uint32_t i = 0; i < bindInfo.waitSemaphoreCount; ++i) { 1025601a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes VkSemaphore semaphore = bindInfo.pWaitSemaphores[i]; 102579a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pSemaphore = GetSemaphoreNode(dev_data, semaphore); 1025801a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes if (pSemaphore) { 1025901a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes if (pSemaphore->signaled) { 102609867daedbf52debc77d6568162ee21e071699b80Chris Forbes if (pSemaphore->signaler.first != VK_NULL_HANDLE) { 102619867daedbf52debc77d6568162ee21e071699b80Chris Forbes semaphore_waits.push_back({semaphore, pSemaphore->signaler.first, pSemaphore->signaler.second}); 102629867daedbf52debc77d6568162ee21e071699b80Chris Forbes pSemaphore->in_use.fetch_add(1); 102639867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 102649867daedbf52debc77d6568162ee21e071699b80Chris Forbes pSemaphore->signaler.first = VK_NULL_HANDLE; 1026501a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes pSemaphore->signaled = false; 102661344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis } else { 10267226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis skip_call |= log_msg( 10268226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT, 10269226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis reinterpret_cast<const uint64_t &>(semaphore), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS", 10270226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "vkQueueBindSparse: Queue 0x%p is waiting on semaphore 0x%" PRIx64 " that has no way to be signaled.", 10271226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis queue, reinterpret_cast<const uint64_t &>(semaphore)); 102725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 102735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 102745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 102751344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis for (uint32_t i = 0; i < bindInfo.signalSemaphoreCount; ++i) { 1027601a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes VkSemaphore semaphore = bindInfo.pSignalSemaphores[i]; 102779a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pSemaphore = GetSemaphoreNode(dev_data, semaphore); 1027801a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes if (pSemaphore) { 1027901a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes if (pSemaphore->signaled) { 102805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis skip_call = 102815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT, 102821344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis reinterpret_cast<const uint64_t &>(semaphore), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS", 10283226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "vkQueueBindSparse: Queue 0x%p is signaling semaphore 0x%" PRIx64 102841344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis ", but that semaphore is already signaled.", 10285226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis queue, reinterpret_cast<const uint64_t &>(semaphore)); 10286bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski } else { 102879867daedbf52debc77d6568162ee21e071699b80Chris Forbes pSemaphore->signaler.first = queue; 102889867daedbf52debc77d6568162ee21e071699b80Chris Forbes pSemaphore->signaler.second = pQueue->seq + pQueue->submissions.size() + 1; 102899867daedbf52debc77d6568162ee21e071699b80Chris Forbes pSemaphore->signaled = true; 102909867daedbf52debc77d6568162ee21e071699b80Chris Forbes pSemaphore->in_use.fetch_add(1); 102919867daedbf52debc77d6568162ee21e071699b80Chris Forbes semaphore_signals.push_back(semaphore); 102929867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 102935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 102945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 102959867daedbf52debc77d6568162ee21e071699b80Chris Forbes 10296bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pQueue->submissions.emplace_back(std::vector<VkCommandBuffer>(), semaphore_waits, semaphore_signals, 102979867daedbf52debc77d6568162ee21e071699b80Chris Forbes bindIdx == bindInfoCount - 1 ? fence : VK_NULL_HANDLE); 102985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 102999867daedbf52debc77d6568162ee21e071699b80Chris Forbes 103009867daedbf52debc77d6568162ee21e071699b80Chris Forbes if (pFence && !bindInfoCount) { 103019867daedbf52debc77d6568162ee21e071699b80Chris Forbes // No work to do, just dropping a fence in the queue by itself. 10302bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pQueue->submissions.emplace_back(std::vector<VkCommandBuffer>(), std::vector<SEMAPHORE_WAIT>(), std::vector<VkSemaphore>(), 103039867daedbf52debc77d6568162ee21e071699b80Chris Forbes fence); 103049867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 103059867daedbf52debc77d6568162ee21e071699b80Chris Forbes 10306b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 103075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10308cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) return dev_data->dispatch_table.QueueBindSparse(queue, bindInfoCount, pBindInfo, fence); 103095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 103105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 103115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 103125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1031389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateSemaphore(VkDevice device, const VkSemaphoreCreateInfo *pCreateInfo, 1031489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkSemaphore *pSemaphore) { 1031556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 103164a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateSemaphore(device, pCreateInfo, pAllocator, pSemaphore); 103175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (result == VK_SUCCESS) { 10318b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 10319bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SEMAPHORE_NODE *sNode = &dev_data->semaphoreMap[*pSemaphore]; 103209867daedbf52debc77d6568162ee21e071699b80Chris Forbes sNode->signaler.first = VK_NULL_HANDLE; 103219867daedbf52debc77d6568162ee21e071699b80Chris Forbes sNode->signaler.second = 0; 103221344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis sNode->signaled = false; 103235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 103245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 103255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 103265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10327bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateEvent(VkDevice device, const VkEventCreateInfo *pCreateInfo, 10328bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkEvent *pEvent) { 1032956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 103304a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateEvent(device, pCreateInfo, pAllocator, pEvent); 103315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (result == VK_SUCCESS) { 10332b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 103335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->eventMap[*pEvent].needsSignaled = false; 10334293ecfc5e69ed3978a8c04518166d828294870a4Tony Barbour dev_data->eventMap[*pEvent].write_in_use = 0; 103355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->eventMap[*pEvent].stageMask = VkPipelineStageFlags(0); 103365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 103375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 103385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 103395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 103409ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinskistatic bool PreCallValidateCreateSwapchainKHR(layer_data *dev_data, const char *func_name, 103419ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski VkSwapchainCreateInfoKHR const *pCreateInfo, SURFACE_STATE *surface_state, 103429ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski SWAPCHAIN_NODE *old_swapchain_state) { 10343d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes auto most_recent_swapchain = surface_state->swapchain ? surface_state->swapchain : surface_state->old_swapchain; 10344d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes 103454bd5f453535de3d3423ff1f9995b4acb15f791d2Chris Forbes // TODO: revisit this. some of these rules are being relaxed. 10346d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes if (most_recent_swapchain != old_swapchain_state || (surface_state->old_swapchain && surface_state->swapchain)) { 10347d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 10348d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes reinterpret_cast<uint64_t>(dev_data->device), __LINE__, DRAWSTATE_SWAPCHAIN_ALREADY_EXISTS, "DS", 103499ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s: surface has an existing swapchain other than oldSwapchain", func_name)) 10350d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes return true; 10351d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes } 10352d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes if (old_swapchain_state && old_swapchain_state->createInfo.surface != pCreateInfo->surface) { 10353d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 10354d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes reinterpret_cast<uint64_t const &>(pCreateInfo->oldSwapchain), __LINE__, DRAWSTATE_SWAPCHAIN_WRONG_SURFACE, 103559ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "DS", "%s: pCreateInfo->oldSwapchain's surface is not pCreateInfo->surface", func_name)) 10356d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes return true; 10357d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes } 103589a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto physical_device_state = GetPhysicalDeviceState(dev_data->instance_data, dev_data->physical_device); 103597de258f87ca1192db116a66b209253793d276ebcChris Forbes if (physical_device_state->vkGetPhysicalDeviceSurfaceCapabilitiesKHRState == UNCALLED) { 103607de258f87ca1192db116a66b209253793d276ebcChris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 103617de258f87ca1192db116a66b209253793d276ebcChris Forbes reinterpret_cast<uint64_t>(dev_data->physical_device), __LINE__, DRAWSTATE_SWAPCHAIN_CREATE_BEFORE_QUERY, "DS", 103629ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s: surface capabilities not retrieved for this physical device", func_name)) 103637de258f87ca1192db116a66b209253793d276ebcChris Forbes return true; 10364cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else { // have valid capabilities 103655c99b4daed164798f307244c9bde17b4f66014fbChris Forbes auto &capabilities = physical_device_state->surfaceCapabilities; 103669ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // Validate pCreateInfo->minImageCount against VkSurfaceCapabilitiesKHR::{min|max}ImageCount: 103672fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen if (pCreateInfo->minImageCount < capabilities.minImageCount) { 103682fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 103692fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t>(dev_data->device), __LINE__, VALIDATION_ERROR_02331, "DS", 103709ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s called with minImageCount = %d, which is outside the bounds returned " 103712fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen "by vkGetPhysicalDeviceSurfaceCapabilitiesKHR() (i.e. minImageCount = %d, maxImageCount = %d). %s", 103729ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski func_name, pCreateInfo->minImageCount, capabilities.minImageCount, capabilities.maxImageCount, 103732fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen validation_error_map[VALIDATION_ERROR_02331])) 103742fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen return true; 103752fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen } 103762fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen 103772fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen if ((capabilities.maxImageCount > 0) && (pCreateInfo->minImageCount > capabilities.maxImageCount)) { 103785c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 103792fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t>(dev_data->device), __LINE__, VALIDATION_ERROR_02332, "DS", 103809ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s called with minImageCount = %d, which is outside the bounds returned " 103812fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen "by vkGetPhysicalDeviceSurfaceCapabilitiesKHR() (i.e. minImageCount = %d, maxImageCount = %d). %s", 103829ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski func_name, pCreateInfo->minImageCount, capabilities.minImageCount, capabilities.maxImageCount, 103832fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen validation_error_map[VALIDATION_ERROR_02332])) 103845c99b4daed164798f307244c9bde17b4f66014fbChris Forbes return true; 103855c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 103862fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen 103879ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // Validate pCreateInfo->imageExtent against VkSurfaceCapabilitiesKHR::{current|min|max}ImageExtent: 103882e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill if ((capabilities.currentExtent.width == kSurfaceSizeFromSwapchain) && 103892e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill ((pCreateInfo->imageExtent.width < capabilities.minImageExtent.width) || 103902e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill (pCreateInfo->imageExtent.width > capabilities.maxImageExtent.width) || 103912e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill (pCreateInfo->imageExtent.height < capabilities.minImageExtent.height) || 103922e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill (pCreateInfo->imageExtent.height > capabilities.maxImageExtent.height))) { 103935c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 103942fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t>(dev_data->device), __LINE__, VALIDATION_ERROR_02334, "DS", 103959ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s called with imageExtent = (%d,%d), which is outside the bounds returned by " 103969ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "vkGetPhysicalDeviceSurfaceCapabilitiesKHR(): currentExtent = (%d,%d), minImageExtent = (%d,%d), " 103979ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "maxImageExtent = (%d,%d). %s", 103989ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski func_name, pCreateInfo->imageExtent.width, pCreateInfo->imageExtent.height, 103999ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski capabilities.currentExtent.width, capabilities.currentExtent.height, capabilities.minImageExtent.width, 104009ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski capabilities.minImageExtent.height, capabilities.maxImageExtent.width, capabilities.maxImageExtent.height, 104012fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen validation_error_map[VALIDATION_ERROR_02334])) 104025c99b4daed164798f307244c9bde17b4f66014fbChris Forbes return true; 104035c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 104042e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill if ((capabilities.currentExtent.width != kSurfaceSizeFromSwapchain) && 104052e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill ((pCreateInfo->imageExtent.width != capabilities.currentExtent.width) || 104062e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill (pCreateInfo->imageExtent.height != capabilities.currentExtent.height))) { 104075c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 104082fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t>(dev_data->device), __LINE__, VALIDATION_ERROR_02334, "DS", 104099ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s called with imageExtent = (%d,%d), which is not equal to the currentExtent = (%d,%d) returned by " 104109ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "vkGetPhysicalDeviceSurfaceCapabilitiesKHR(). %s", 104119ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski func_name, pCreateInfo->imageExtent.width, pCreateInfo->imageExtent.height, 104129ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski capabilities.currentExtent.width, capabilities.currentExtent.height, 104132fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen validation_error_map[VALIDATION_ERROR_02334])) 104145c99b4daed164798f307244c9bde17b4f66014fbChris Forbes return true; 104155c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 104169ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // pCreateInfo->preTransform should have exactly one bit set, and that bit must also be set in 104179ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // VkSurfaceCapabilitiesKHR::supportedTransforms. 104185c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (!pCreateInfo->preTransform || (pCreateInfo->preTransform & (pCreateInfo->preTransform - 1)) || 104195c99b4daed164798f307244c9bde17b4f66014fbChris Forbes !(pCreateInfo->preTransform & capabilities.supportedTransforms)) { 104209ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // This is an error situation; one for which we'd like to give the developer a helpful, multi-line error message. Build 104219ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // it up a little at a time, and then log it: 104225c99b4daed164798f307244c9bde17b4f66014fbChris Forbes std::string errorString = ""; 104235c99b4daed164798f307244c9bde17b4f66014fbChris Forbes char str[1024]; 104245c99b4daed164798f307244c9bde17b4f66014fbChris Forbes // Here's the first part of the message: 104259ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski sprintf(str, "%s called with a non-supported pCreateInfo->preTransform (i.e. %s). Supported values are:\n", func_name, 104265c99b4daed164798f307244c9bde17b4f66014fbChris Forbes string_VkSurfaceTransformFlagBitsKHR(pCreateInfo->preTransform)); 104275c99b4daed164798f307244c9bde17b4f66014fbChris Forbes errorString += str; 104285c99b4daed164798f307244c9bde17b4f66014fbChris Forbes for (int i = 0; i < 32; i++) { 104295c99b4daed164798f307244c9bde17b4f66014fbChris Forbes // Build up the rest of the message: 104305c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if ((1 << i) & capabilities.supportedTransforms) { 104315c99b4daed164798f307244c9bde17b4f66014fbChris Forbes const char *newStr = string_VkSurfaceTransformFlagBitsKHR((VkSurfaceTransformFlagBitsKHR)(1 << i)); 104325c99b4daed164798f307244c9bde17b4f66014fbChris Forbes sprintf(str, " %s\n", newStr); 104335c99b4daed164798f307244c9bde17b4f66014fbChris Forbes errorString += str; 104345c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 104355c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 104365c99b4daed164798f307244c9bde17b4f66014fbChris Forbes // Log the message that we've built up: 104375c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 104382fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t &>(dev_data->device), __LINE__, VALIDATION_ERROR_02339, "DS", "%s. %s", 104392fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen errorString.c_str(), validation_error_map[VALIDATION_ERROR_02339])) 104405c99b4daed164798f307244c9bde17b4f66014fbChris Forbes return true; 104415c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 104427b0d28d116977b91892f354e002edd760bdb86cbChris Forbes 104439ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // pCreateInfo->compositeAlpha should have exactly one bit set, and that bit must also be set in 104449ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // VkSurfaceCapabilitiesKHR::supportedCompositeAlpha 104455c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (!pCreateInfo->compositeAlpha || (pCreateInfo->compositeAlpha & (pCreateInfo->compositeAlpha - 1)) || 104465c99b4daed164798f307244c9bde17b4f66014fbChris Forbes !((pCreateInfo->compositeAlpha) & capabilities.supportedCompositeAlpha)) { 104479ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // This is an error situation; one for which we'd like to give the developer a helpful, multi-line error message. Build 104489ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // it up a little at a time, and then log it: 104495c99b4daed164798f307244c9bde17b4f66014fbChris Forbes std::string errorString = ""; 104505c99b4daed164798f307244c9bde17b4f66014fbChris Forbes char str[1024]; 104515c99b4daed164798f307244c9bde17b4f66014fbChris Forbes // Here's the first part of the message: 104529ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski sprintf(str, "%s called with a non-supported pCreateInfo->compositeAlpha (i.e. %s). Supported values are:\n", 104539ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski func_name, string_VkCompositeAlphaFlagBitsKHR(pCreateInfo->compositeAlpha)); 104545c99b4daed164798f307244c9bde17b4f66014fbChris Forbes errorString += str; 104555c99b4daed164798f307244c9bde17b4f66014fbChris Forbes for (int i = 0; i < 32; i++) { 104565c99b4daed164798f307244c9bde17b4f66014fbChris Forbes // Build up the rest of the message: 104575c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if ((1 << i) & capabilities.supportedCompositeAlpha) { 104585c99b4daed164798f307244c9bde17b4f66014fbChris Forbes const char *newStr = string_VkCompositeAlphaFlagBitsKHR((VkCompositeAlphaFlagBitsKHR)(1 << i)); 104595c99b4daed164798f307244c9bde17b4f66014fbChris Forbes sprintf(str, " %s\n", newStr); 104605c99b4daed164798f307244c9bde17b4f66014fbChris Forbes errorString += str; 104615c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 104625c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 104635c99b4daed164798f307244c9bde17b4f66014fbChris Forbes // Log the message that we've built up: 104645c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 104652fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t &>(dev_data->device), __LINE__, VALIDATION_ERROR_02340, "DS", "%s. %s", 104662fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen errorString.c_str(), validation_error_map[VALIDATION_ERROR_02340])) 104675c99b4daed164798f307244c9bde17b4f66014fbChris Forbes return true; 104685c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 104699ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // Validate pCreateInfo->imageArrayLayers against VkSurfaceCapabilitiesKHR::maxImageArrayLayers: 104705c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if ((pCreateInfo->imageArrayLayers < 1) || (pCreateInfo->imageArrayLayers > capabilities.maxImageArrayLayers)) { 104715c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 104722fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t>(dev_data->device), __LINE__, VALIDATION_ERROR_02335, "DS", 104739ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s called with a non-supported imageArrayLayers (i.e. %d). Minimum value is 1, maximum value is %d. %s", 104749ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski func_name, pCreateInfo->imageArrayLayers, capabilities.maxImageArrayLayers, 104752fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen validation_error_map[VALIDATION_ERROR_02335])) 104765c99b4daed164798f307244c9bde17b4f66014fbChris Forbes return true; 104775c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 104789ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // Validate pCreateInfo->imageUsage against VkSurfaceCapabilitiesKHR::supportedUsageFlags: 104795c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (pCreateInfo->imageUsage != (pCreateInfo->imageUsage & capabilities.supportedUsageFlags)) { 104805c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 104812fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t>(dev_data->device), __LINE__, VALIDATION_ERROR_02336, "DS", 104829ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s called with a non-supported pCreateInfo->imageUsage (i.e. 0x%08x). Supported flag bits are 0x%08x. %s", 104839ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski func_name, pCreateInfo->imageUsage, capabilities.supportedUsageFlags, 104849ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski validation_error_map[VALIDATION_ERROR_02336])) 104855c99b4daed164798f307244c9bde17b4f66014fbChris Forbes return true; 104865c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 104877de258f87ca1192db116a66b209253793d276ebcChris Forbes } 10488d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes 104899ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // Validate pCreateInfo values with the results of vkGetPhysicalDeviceSurfaceFormatsKHR(): 104905faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (physical_device_state->vkGetPhysicalDeviceSurfaceFormatsKHRState != QUERY_DETAILS) { 104915faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 104925faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes reinterpret_cast<uint64_t>(dev_data->device), __LINE__, DRAWSTATE_SWAPCHAIN_CREATE_BEFORE_QUERY, "DS", 104939ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s called before calling vkGetPhysicalDeviceSurfaceFormatsKHR().", func_name)) 104945faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes return true; 104955faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } else { 104969ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // Validate pCreateInfo->imageFormat against VkSurfaceFormatKHR::format: 104975faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes bool foundFormat = false; 104985faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes bool foundColorSpace = false; 104995faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes bool foundMatch = false; 105005faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes for (auto const &format : physical_device_state->surface_formats) { 105015faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (pCreateInfo->imageFormat == format.format) { 105029ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // Validate pCreateInfo->imageColorSpace against VkSurfaceFormatKHR::colorSpace: 105035faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes foundFormat = true; 105045faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (pCreateInfo->imageColorSpace == format.colorSpace) { 105055faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes foundMatch = true; 105065faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes break; 105075faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 105085faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } else { 105095faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (pCreateInfo->imageColorSpace == format.colorSpace) { 105105faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes foundColorSpace = true; 105115faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 105125faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 105135faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 105145faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (!foundMatch) { 105155faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (!foundFormat) { 105165faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 105172fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t>(dev_data->device), __LINE__, VALIDATION_ERROR_02333, "DS", 10518bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "%s called with a non-supported pCreateInfo->imageFormat (i.e. %d). %s", func_name, 10519bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pCreateInfo->imageFormat, validation_error_map[VALIDATION_ERROR_02333])) 105202fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen return true; 105212fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen } 105222fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen if (!foundColorSpace) { 105232fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 105242fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t>(dev_data->device), __LINE__, VALIDATION_ERROR_02333, "DS", 10525bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "%s called with a non-supported pCreateInfo->imageColorSpace (i.e. %d). %s", func_name, 10526bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pCreateInfo->imageColorSpace, validation_error_map[VALIDATION_ERROR_02333])) 105275faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes return true; 105285faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 105295faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 105305faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 105315faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes 105329ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // Validate pCreateInfo values with the results of vkGetPhysicalDeviceSurfacePresentModesKHR(): 105339e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (physical_device_state->vkGetPhysicalDeviceSurfacePresentModesKHRState != QUERY_DETAILS) { 1053425002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // FIFO is required to always be supported 105359e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (pCreateInfo->presentMode != VK_PRESENT_MODE_FIFO_KHR) { 105369e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 105379ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski reinterpret_cast<uint64_t>(dev_data->device), __LINE__, DRAWSTATE_SWAPCHAIN_CREATE_BEFORE_QUERY, "DS", 105389ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s called before calling vkGetPhysicalDeviceSurfacePresentModesKHR().", func_name)) 105399e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes return true; 105409e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 105419e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } else { 105429ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // Validate pCreateInfo->presentMode against vkGetPhysicalDeviceSurfacePresentModesKHR(): 10543bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski bool foundMatch = std::find(physical_device_state->present_modes.begin(), physical_device_state->present_modes.end(), 105449e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes pCreateInfo->presentMode) != physical_device_state->present_modes.end(); 105459e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (!foundMatch) { 105469e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 105472fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t>(dev_data->device), __LINE__, VALIDATION_ERROR_02341, "DS", 105489ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s called with a non-supported presentMode (i.e. %s). %s", func_name, 105492fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen string_VkPresentModeKHR(pCreateInfo->presentMode), validation_error_map[VALIDATION_ERROR_02341])) 105509e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes return true; 105519e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 105529e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 105539e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes 10554d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes return false; 10555d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes} 10556d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes 10557261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinskistatic void PostCallRecordCreateSwapchainKHR(layer_data *dev_data, VkResult result, const VkSwapchainCreateInfoKHR *pCreateInfo, 10558261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski VkSwapchainKHR *pSwapchain, SURFACE_STATE *surface_state, 10559261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski SWAPCHAIN_NODE *old_swapchain_state) { 105605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 10561b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 10562ddc5201048319558ce66701163a4546ee957af19Chris Forbes auto swapchain_state = unique_ptr<SWAPCHAIN_NODE>(new SWAPCHAIN_NODE(pCreateInfo, *pSwapchain)); 10563ddc5201048319558ce66701163a4546ee957af19Chris Forbes surface_state->swapchain = swapchain_state.get(); 10564ddc5201048319558ce66701163a4546ee957af19Chris Forbes dev_data->device_extensions.swapchainMap[*pSwapchain] = std::move(swapchain_state); 10565ddc5201048319558ce66701163a4546ee957af19Chris Forbes } else { 10566ddc5201048319558ce66701163a4546ee957af19Chris Forbes surface_state->swapchain = nullptr; 105675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 10568ddc5201048319558ce66701163a4546ee957af19Chris Forbes // Spec requires that even if CreateSwapchainKHR fails, oldSwapchain behaves as replaced. 105695b5488456e5afa0487f95b805a2aba59b13d69f4Chris Forbes if (old_swapchain_state) { 105705b5488456e5afa0487f95b805a2aba59b13d69f4Chris Forbes old_swapchain_state->replaced = true; 105715b5488456e5afa0487f95b805a2aba59b13d69f4Chris Forbes } 10572ddc5201048319558ce66701163a4546ee957af19Chris Forbes surface_state->old_swapchain = old_swapchain_state; 10573261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski return; 10574261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski} 10575261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski 10576261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo, 10577261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchain) { 1057856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 105799a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto surface_state = GetSurfaceState(dev_data->instance_data, pCreateInfo->surface); 105809a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto old_swapchain_state = GetSwapchainNode(dev_data, pCreateInfo->oldSwapchain); 10581261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski 105829ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski if (PreCallValidateCreateSwapchainKHR(dev_data, "vkCreateSwapChainKHR()", pCreateInfo, surface_state, old_swapchain_state)) { 10583261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski return VK_ERROR_VALIDATION_FAILED_EXT; 10584261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski } 10585261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski 10586261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski VkResult result = dev_data->dispatch_table.CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain); 10587261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski 10588261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski PostCallRecordCreateSwapchainKHR(dev_data, result, pCreateInfo, pSwapchain, surface_state, old_swapchain_state); 10589ddc5201048319558ce66701163a4546ee957af19Chris Forbes 105905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 105915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 105925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10593bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks *pAllocator) { 1059456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 1059583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 105965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10597b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 105989a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto swapchain_data = GetSwapchainNode(dev_data, swapchain); 10599b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis if (swapchain_data) { 10600b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis if (swapchain_data->images.size() > 0) { 10601b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis for (auto swapchain_image : swapchain_data->images) { 106025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto image_sub = dev_data->imageSubresourceMap.find(swapchain_image); 106035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (image_sub != dev_data->imageSubresourceMap.end()) { 106045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto imgsubpair : image_sub->second) { 106055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto image_item = dev_data->imageLayoutMap.find(imgsubpair); 106065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (image_item != dev_data->imageLayoutMap.end()) { 106075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->imageLayoutMap.erase(image_item); 106085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 106095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 106105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->imageSubresourceMap.erase(image_sub); 106115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 1061283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call = 10613f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis ClearMemoryObjectBindings(dev_data, (uint64_t)swapchain_image, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT); 1061494c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis dev_data->imageMap.erase(swapchain_image); 106155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 106165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 10617ddc5201048319558ce66701163a4546ee957af19Chris Forbes 106189a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto surface_state = GetSurfaceState(dev_data->instance_data, swapchain_data->createInfo.surface); 10619ddc5201048319558ce66701163a4546ee957af19Chris Forbes if (surface_state) { 10620cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (surface_state->swapchain == swapchain_data) surface_state->swapchain = nullptr; 10621cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (surface_state->old_swapchain == swapchain_data) surface_state->old_swapchain = nullptr; 10622ddc5201048319558ce66701163a4546ee957af19Chris Forbes } 10623ddc5201048319558ce66701163a4546ee957af19Chris Forbes 106245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->device_extensions.swapchainMap.erase(swapchain); 106255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 10626b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 10627cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.DestroySwapchainKHR(device, swapchain, pAllocator); 106285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 106295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10630bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL GetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t *pCount, 10631bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkImage *pSwapchainImages) { 1063256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 106334a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.GetSwapchainImagesKHR(device, swapchain, pCount, pSwapchainImages); 106345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 106355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (result == VK_SUCCESS && pSwapchainImages != NULL) { 106365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // This should never happen and is checked by param checker. 10637cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!pCount) return result; 10638b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 106395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const size_t count = *pCount; 106409a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto swapchain_node = GetSwapchainNode(dev_data, swapchain); 10641b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis if (swapchain_node && !swapchain_node->images.empty()) { 106420801763633180d277d26a90343464bd11646056fTobin Ehlis // TODO : Not sure I like the memcmp here, but it works 106430801763633180d277d26a90343464bd11646056fTobin Ehlis const bool mismatch = (swapchain_node->images.size() != count || 106440801763633180d277d26a90343464bd11646056fTobin Ehlis memcmp(&swapchain_node->images[0], pSwapchainImages, sizeof(swapchain_node->images[0]) * count)); 106455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (mismatch) { 106465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODO: Verify against Valid Usage section of extension 106475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 106485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (uint64_t)swapchain, __LINE__, MEMTRACK_NONE, "SWAP_CHAIN", 10649414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller "vkGetSwapchainInfoKHR(0x%" PRIx64 106505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis ", VK_SWAP_CHAIN_INFO_TYPE_PERSISTENT_IMAGES_KHR) returned mismatching data", 106515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (uint64_t)(swapchain)); 106525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 106535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 106545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < *pCount; ++i) { 106555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis IMAGE_LAYOUT_NODE image_layout_node; 106565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis image_layout_node.layout = VK_IMAGE_LAYOUT_UNDEFINED; 106575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis image_layout_node.format = swapchain_node->createInfo.imageFormat; 106586d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis // Add imageMap entries for each swapchain image 106596d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis VkImageCreateInfo image_ci = {}; 106606d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis image_ci.mipLevels = 1; 106616d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis image_ci.arrayLayers = swapchain_node->createInfo.imageArrayLayers; 106626d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis image_ci.usage = swapchain_node->createInfo.imageUsage; 106636d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis image_ci.format = swapchain_node->createInfo.imageFormat; 1066441ebcb6b517b1de5ae456d46d866f5e84a96a2c5Tobin Ehlis image_ci.samples = VK_SAMPLE_COUNT_1_BIT; 106656d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis image_ci.extent.width = swapchain_node->createInfo.imageExtent.width; 106666d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis image_ci.extent.height = swapchain_node->createInfo.imageExtent.height; 106676d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis image_ci.sharingMode = swapchain_node->createInfo.imageSharingMode; 106681facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis dev_data->imageMap[pSwapchainImages[i]] = unique_ptr<IMAGE_STATE>(new IMAGE_STATE(pSwapchainImages[i], &image_ci)); 106691facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis auto &image_state = dev_data->imageMap[pSwapchainImages[i]]; 106701facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis image_state->valid = false; 10671e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis image_state->binding.mem = MEMTRACKER_SWAP_CHAIN_IMAGE_KEY; 106725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis swapchain_node->images.push_back(pSwapchainImages[i]); 106735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis ImageSubresourcePair subpair = {pSwapchainImages[i], false, VkImageSubresource()}; 106745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->imageSubresourceMap[pSwapchainImages[i]].push_back(subpair); 106755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->imageLayoutMap[subpair] = image_layout_node; 106765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->device_extensions.imageToSwapchainMap[pSwapchainImages[i]] = swapchain; 106775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 106785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 106795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 106805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 106815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1068289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo) { 1068356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map); 106845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool skip_call = false; 106855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 106866c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes std::lock_guard<std::mutex> lock(global_lock); 106879a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto queue_state = GetQueueState(dev_data, queue); 106881671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes 106896c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes for (uint32_t i = 0; i < pPresentInfo->waitSemaphoreCount; ++i) { 106909a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pSemaphore = GetSemaphoreNode(dev_data, pPresentInfo->pWaitSemaphores[i]); 106916c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes if (pSemaphore && !pSemaphore->signaled) { 10692226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 10693226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, 10694226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "DS", "Queue 0x%p is waiting on semaphore 0x%" PRIx64 " that has no way to be signaled.", queue, 10695226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis reinterpret_cast<const uint64_t &>(pPresentInfo->pWaitSemaphores[i])); 106965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 106976c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes } 10698249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis 106996c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes for (uint32_t i = 0; i < pPresentInfo->swapchainCount; ++i) { 107009a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto swapchain_data = GetSwapchainNode(dev_data, pPresentInfo->pSwapchains[i]); 10701a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes if (swapchain_data) { 10702a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes if (pPresentInfo->pImageIndices[i] >= swapchain_data->images.size()) { 10703bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski skip_call |= log_msg( 10704bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 10705bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski reinterpret_cast<uint64_t const &>(pPresentInfo->pSwapchains[i]), __LINE__, DRAWSTATE_SWAPCHAIN_INVALID_IMAGE, 10706bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "DS", "vkQueuePresentKHR: Swapchain image index too large (%u). There are only %u images in this swapchain.", 10707bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pPresentInfo->pImageIndices[i], (uint32_t)swapchain_data->images.size()); 10708bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski } else { 10709a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes auto image = swapchain_data->images[pPresentInfo->pImageIndices[i]]; 107109a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_state = GetImageState(dev_data, image); 107111facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis skip_call |= ValidateImageMemoryIsValid(dev_data, image_state, "vkQueuePresentKHR()"); 10712a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes 107131facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis if (!image_state->acquired) { 10714bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski skip_call |= log_msg( 10715bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 10716bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski reinterpret_cast<uint64_t const &>(pPresentInfo->pSwapchains[i]), __LINE__, 10717bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski DRAWSTATE_SWAPCHAIN_IMAGE_NOT_ACQUIRED, "DS", 10718bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "vkQueuePresentKHR: Swapchain image index %u has not been acquired.", pPresentInfo->pImageIndices[i]); 10719a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes } 10720a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes 10721a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes vector<VkImageLayout> layouts; 10722a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes if (FindLayouts(dev_data, image, layouts)) { 10723a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes for (auto layout : layouts) { 10724a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes if (layout != VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) { 10725a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes skip_call |= 107262fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT, 107272fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t &>(queue), __LINE__, VALIDATION_ERROR_01964, "DS", 107282fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen "Images passed to present must be in layout " 107292fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen "VK_IMAGE_LAYOUT_PRESENT_SRC_KHR but is in %s. %s", 107302fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen string_VkImageLayout(layout), validation_error_map[VALIDATION_ERROR_01964]); 10731a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes } 107325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 107335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 107345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 107351671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes 107361671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes // All physical devices and queue families are required to be able 107371671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes // to present to any native window on Android; require the 107381671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes // application to have established support on any other platform. 107391671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes if (!dev_data->instance_data->androidSurfaceExtensionEnabled) { 107409a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto surface_state = GetSurfaceState(dev_data->instance_data, swapchain_data->createInfo.surface); 107411671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes auto support_it = surface_state->gpu_queue_support.find({dev_data->physical_device, queue_state->queueFamilyIndex}); 107421671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes 107431671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes if (support_it == surface_state->gpu_queue_support.end()) { 107441671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes skip_call |= 107451671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 107461671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes reinterpret_cast<uint64_t const &>(pPresentInfo->pSwapchains[i]), __LINE__, 10747cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski DRAWSTATE_SWAPCHAIN_UNSUPPORTED_QUEUE, "DS", 10748cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkQueuePresentKHR: Presenting image without calling " 10749cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkGetPhysicalDeviceSurfaceSupportKHR"); 107501671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes } else if (!support_it->second) { 10751cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski skip_call |= log_msg( 10752cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 10753cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski reinterpret_cast<uint64_t const &>(pPresentInfo->pSwapchains[i]), __LINE__, VALIDATION_ERROR_01961, "DS", 10754cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkQueuePresentKHR: Presenting image on queue that cannot " 10755cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "present to this surface. %s", 10756cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski validation_error_map[VALIDATION_ERROR_01961]); 107571671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes } 107581671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes } 107595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 107605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 107615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 107626c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes if (skip_call) { 107636c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes return VK_ERROR_VALIDATION_FAILED_EXT; 107646c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes } 107656c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes 107664a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.QueuePresentKHR(queue, pPresentInfo); 107676c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes 107686c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes if (result != VK_ERROR_VALIDATION_FAILED_EXT) { 107696c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes // Semaphore waits occur before error generation, if the call reached 107706c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes // the ICD. (Confirm?) 107716c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes for (uint32_t i = 0; i < pPresentInfo->waitSemaphoreCount; ++i) { 107729a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pSemaphore = GetSemaphoreNode(dev_data, pPresentInfo->pWaitSemaphores[i]); 107739867daedbf52debc77d6568162ee21e071699b80Chris Forbes if (pSemaphore) { 107749867daedbf52debc77d6568162ee21e071699b80Chris Forbes pSemaphore->signaler.first = VK_NULL_HANDLE; 107756c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes pSemaphore->signaled = false; 107766c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes } 107776c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes } 107789867daedbf52debc77d6568162ee21e071699b80Chris Forbes 10779220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes for (uint32_t i = 0; i < pPresentInfo->swapchainCount; ++i) { 10780220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes // Note: this is imperfect, in that we can get confused about what 10781220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes // did or didn't succeed-- but if the app does that, it's confused 10782220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes // itself just as much. 10783220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes auto local_result = pPresentInfo->pResults ? pPresentInfo->pResults[i] : result; 10784220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes 10785cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (local_result != VK_SUCCESS && local_result != VK_SUBOPTIMAL_KHR) continue; // this present didn't actually happen. 10786220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes 10787220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes // Mark the image as having been released to the WSI 107889a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto swapchain_data = GetSwapchainNode(dev_data, pPresentInfo->pSwapchains[i]); 10789220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes auto image = swapchain_data->images[pPresentInfo->pImageIndices[i]]; 107909a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_state = GetImageState(dev_data, image); 107911facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis image_state->acquired = false; 10792220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes } 10793220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes 107949867daedbf52debc77d6568162ee21e071699b80Chris Forbes // Note: even though presentation is directed to a queue, there is no 107959867daedbf52debc77d6568162ee21e071699b80Chris Forbes // direct ordering between QP and subsequent work, so QP (and its 107969867daedbf52debc77d6568162ee21e071699b80Chris Forbes // semaphore waits) /never/ participate in any completion proof. 107976c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes } 107981344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis 107995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 108005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 108015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10802c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinskistatic bool PreCallValidateCreateSharedSwapchainsKHR(layer_data *dev_data, uint32_t swapchainCount, 10803c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski const VkSwapchainCreateInfoKHR *pCreateInfos, VkSwapchainKHR *pSwapchains, 10804c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski std::vector<SURFACE_STATE *> &surface_state, 10805c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski std::vector<SWAPCHAIN_NODE *> &old_swapchain_state) { 108060342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski if (pCreateInfos) { 10807c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski std::lock_guard<std::mutex> lock(global_lock); 108080342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski for (uint32_t i = 0; i < swapchainCount; i++) { 108099a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis surface_state.push_back(GetSurfaceState(dev_data->instance_data, pCreateInfos[i].surface)); 108109a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis old_swapchain_state.push_back(GetSwapchainNode(dev_data, pCreateInfos[i].oldSwapchain)); 108119ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski std::stringstream func_name; 108129ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski func_name << "vkCreateSharedSwapchainsKHR[" << swapchainCount << "]"; 10813bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (PreCallValidateCreateSwapchainKHR(dev_data, func_name.str().c_str(), &pCreateInfos[i], surface_state[i], 10814bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski old_swapchain_state[i])) { 10815c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski return true; 108160342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski } 108170342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski } 108180342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski } 10819c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski return false; 10820c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski} 108210342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski 10822c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinskistatic void PostCallRecordCreateSharedSwapchainsKHR(layer_data *dev_data, VkResult result, uint32_t swapchainCount, 10823c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski const VkSwapchainCreateInfoKHR *pCreateInfos, VkSwapchainKHR *pSwapchains, 10824c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski std::vector<SURFACE_STATE *> &surface_state, 10825c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski std::vector<SWAPCHAIN_NODE *> &old_swapchain_state) { 108260342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski if (VK_SUCCESS == result) { 108270342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski for (uint32_t i = 0; i < swapchainCount; i++) { 108280342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski auto swapchain_state = unique_ptr<SWAPCHAIN_NODE>(new SWAPCHAIN_NODE(&pCreateInfos[i], pSwapchains[i])); 108290342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski surface_state[i]->swapchain = swapchain_state.get(); 108300342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski dev_data->device_extensions.swapchainMap[pSwapchains[i]] = std::move(swapchain_state); 108310342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski } 108320342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski } else { 108330342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski for (uint32_t i = 0; i < swapchainCount; i++) { 108340342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski surface_state[i]->swapchain = nullptr; 108350342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski } 108360342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski } 108370342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski // Spec requires that even if CreateSharedSwapchainKHR fails, oldSwapchain behaves as replaced. 108380342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski for (uint32_t i = 0; i < swapchainCount; i++) { 108390342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski if (old_swapchain_state[i]) { 108400342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski old_swapchain_state[i]->replaced = true; 108410342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski } 108420342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski surface_state[i]->old_swapchain = old_swapchain_state[i]; 108430342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski } 10844c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski return; 10845c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski} 10846c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski 10847c6cd632d064579a64e61d8704b411d0e4ace7adaMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateSharedSwapchainsKHR(VkDevice device, uint32_t swapchainCount, 10848c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski const VkSwapchainCreateInfoKHR *pCreateInfos, 10849c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchains) { 1085056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 10851c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski std::vector<SURFACE_STATE *> surface_state; 10852c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski std::vector<SWAPCHAIN_NODE *> old_swapchain_state; 10853c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski 10854c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski if (PreCallValidateCreateSharedSwapchainsKHR(dev_data, swapchainCount, pCreateInfos, pSwapchains, surface_state, 10855c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski old_swapchain_state)) { 10856c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski return VK_ERROR_VALIDATION_FAILED_EXT; 10857c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski } 10858c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski 10859c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski VkResult result = 10860c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski dev_data->dispatch_table.CreateSharedSwapchainsKHR(device, swapchainCount, pCreateInfos, pAllocator, pSwapchains); 10861c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski 10862c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski PostCallRecordCreateSharedSwapchainsKHR(dev_data, result, swapchainCount, pCreateInfos, pSwapchains, surface_state, 10863c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski old_swapchain_state); 108640342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski 10865c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young return result; 10866c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young} 10867c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young 1086889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL AcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, 1086989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu VkSemaphore semaphore, VkFence fence, uint32_t *pImageIndex) { 1087056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 1087183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 108721344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis 10873b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 10874449670637ef4214b33018f497cf10daeff9dc85bChris Forbes 10875449670637ef4214b33018f497cf10daeff9dc85bChris Forbes if (fence == VK_NULL_HANDLE && semaphore == VK_NULL_HANDLE) { 10876449670637ef4214b33018f497cf10daeff9dc85bChris Forbes skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 10877d17d86d15a733f1ec988956721ea4b7cdfb6771bChris Forbes reinterpret_cast<uint64_t &>(device), __LINE__, DRAWSTATE_SWAPCHAIN_NO_SYNC_FOR_ACQUIRE, "DS", 10878449670637ef4214b33018f497cf10daeff9dc85bChris Forbes "vkAcquireNextImageKHR: Semaphore and fence cannot both be VK_NULL_HANDLE. There would be no way " 10879449670637ef4214b33018f497cf10daeff9dc85bChris Forbes "to determine the completion of this operation."); 10880449670637ef4214b33018f497cf10daeff9dc85bChris Forbes } 10881449670637ef4214b33018f497cf10daeff9dc85bChris Forbes 108829a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pSemaphore = GetSemaphoreNode(dev_data, semaphore); 10883f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes if (pSemaphore && pSemaphore->signaled) { 1088483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT, 108852fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<const uint64_t &>(semaphore), __LINE__, VALIDATION_ERROR_01952, "DS", 108862fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen "vkAcquireNextImageKHR: Semaphore must not be currently signaled or in a wait state. %s", 108872fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen validation_error_map[VALIDATION_ERROR_01952]); 108885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 10889f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes 108909a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pFence = GetFenceNode(dev_data, fence); 10891f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes if (pFence) { 1089283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= ValidateFenceForSubmit(dev_data, pFence); 108935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 108944a5614452104c88cb04390dac882dd94ebdcc3deChris Forbes 108959a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto swapchain_data = GetSwapchainNode(dev_data, swapchain); 10896fc9f0448c3cb6ba4fc018fefe761bb43a1884846Chris Forbes 10897fc9f0448c3cb6ba4fc018fefe761bb43a1884846Chris Forbes if (swapchain_data->replaced) { 10898fc9f0448c3cb6ba4fc018fefe761bb43a1884846Chris Forbes skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 10899fc9f0448c3cb6ba4fc018fefe761bb43a1884846Chris Forbes reinterpret_cast<uint64_t &>(swapchain), __LINE__, DRAWSTATE_SWAPCHAIN_REPLACED, "DS", 10900fc9f0448c3cb6ba4fc018fefe761bb43a1884846Chris Forbes "vkAcquireNextImageKHR: This swapchain has been replaced. The application can still " 10901fc9f0448c3cb6ba4fc018fefe761bb43a1884846Chris Forbes "present any images it has acquired, but cannot acquire any more."); 10902fc9f0448c3cb6ba4fc018fefe761bb43a1884846Chris Forbes } 10903fc9f0448c3cb6ba4fc018fefe761bb43a1884846Chris Forbes 109049a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto physical_device_state = GetPhysicalDeviceState(dev_data->instance_data, dev_data->physical_device); 109054a5614452104c88cb04390dac882dd94ebdcc3deChris Forbes if (physical_device_state->vkGetPhysicalDeviceSurfaceCapabilitiesKHRState != UNCALLED) { 109066569ab421f45f905e69fa7345bda4fe5b87e9045Mark Lobodzinski uint64_t acquired_images = std::count_if(swapchain_data->images.begin(), swapchain_data->images.end(), 109079a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis [=](VkImage image) { return GetImageState(dev_data, image)->acquired; }); 109084a5614452104c88cb04390dac882dd94ebdcc3deChris Forbes if (acquired_images > swapchain_data->images.size() - physical_device_state->surfaceCapabilities.minImageCount) { 109096569ab421f45f905e69fa7345bda4fe5b87e9045Mark Lobodzinski skip_call |= 109106569ab421f45f905e69fa7345bda4fe5b87e9045Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 109116569ab421f45f905e69fa7345bda4fe5b87e9045Mark Lobodzinski reinterpret_cast<uint64_t const &>(swapchain), __LINE__, DRAWSTATE_SWAPCHAIN_TOO_MANY_IMAGES, "DS", 109126569ab421f45f905e69fa7345bda4fe5b87e9045Mark Lobodzinski "vkAcquireNextImageKHR: Application has already acquired the maximum number of images (0x%" PRIxLEAST64 ")", 109136569ab421f45f905e69fa7345bda4fe5b87e9045Mark Lobodzinski acquired_images); 109144a5614452104c88cb04390dac882dd94ebdcc3deChris Forbes } 109154a5614452104c88cb04390dac882dd94ebdcc3deChris Forbes } 1091675269fc9e5cc9696ddf3dd28ff201c9b2526dc7aThomas Louis 1091775269fc9e5cc9696ddf3dd28ff201c9b2526dc7aThomas Louis if (swapchain_data->images.size() == 0) { 1091875269fc9e5cc9696ddf3dd28ff201c9b2526dc7aThomas Louis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 1091975269fc9e5cc9696ddf3dd28ff201c9b2526dc7aThomas Louis reinterpret_cast<uint64_t const &>(swapchain), __LINE__, DRAWSTATE_SWAPCHAIN_IMAGES_NOT_FOUND, "DS", 1092075269fc9e5cc9696ddf3dd28ff201c9b2526dc7aThomas Louis "vkAcquireNextImageKHR: No images found to acquire from. Application probably did not call " 1092175269fc9e5cc9696ddf3dd28ff201c9b2526dc7aThomas Louis "vkGetSwapchainImagesKHR after swapchain creation."); 1092275269fc9e5cc9696ddf3dd28ff201c9b2526dc7aThomas Louis } 1092375269fc9e5cc9696ddf3dd28ff201c9b2526dc7aThomas Louis 10924b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 109251344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis 10926cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip_call) return VK_ERROR_VALIDATION_FAILED_EXT; 10927f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes 109284a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.AcquireNextImageKHR(device, swapchain, timeout, semaphore, fence, pImageIndex); 10929f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes 10930f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes lock.lock(); 10931f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes if (result == VK_SUCCESS || result == VK_SUBOPTIMAL_KHR) { 10932f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes if (pFence) { 10933f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes pFence->state = FENCE_INFLIGHT; 10934cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pFence->signaler.first = VK_NULL_HANDLE; // ANI isn't on a queue, so this can't participate in a completion proof. 10935f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes } 10936f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes 10937f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes // A successful call to AcquireNextImageKHR counts as a signal operation on semaphore 10938f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes if (pSemaphore) { 10939f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes pSemaphore->signaled = true; 109409867daedbf52debc77d6568162ee21e071699b80Chris Forbes pSemaphore->signaler.first = VK_NULL_HANDLE; 10941f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes } 10942220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes 10943220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes // Mark the image as acquired. 10944220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes auto image = swapchain_data->images[*pImageIndex]; 109459a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_state = GetImageState(dev_data, image); 109461facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis image_state->acquired = true; 109475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 10948f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes lock.unlock(); 109491344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis 109505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 109515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 109525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10953f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL EnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount, 10954f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski VkPhysicalDevice *pPhysicalDevices) { 1095583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 1095656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 10957bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis assert(instance_data); 10958219f00ffed576643641976122fa1db8e5fce5dc1Chris Forbes 10959bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis // For this instance, flag when vkEnumeratePhysicalDevices goes to QUERY_COUNT and then QUERY_DETAILS 10960bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis if (NULL == pPhysicalDevices) { 10961bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis instance_data->vkEnumeratePhysicalDevicesState = QUERY_COUNT; 10962f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski } else { 10963bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis if (UNCALLED == instance_data->vkEnumeratePhysicalDevicesState) { 10964bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis // Flag warning here. You can call this without having queried the count, but it may not be 10965bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis // robust on platforms with multiple physical devices. 10966bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis skip_call |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, 10967bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, 0, __LINE__, DEVLIMITS_MISSING_QUERY_COUNT, "DL", 10968bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis "Call sequence has vkEnumeratePhysicalDevices() w/ non-NULL pPhysicalDevices. You should first " 10969bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis "call vkEnumeratePhysicalDevices() w/ NULL pPhysicalDevices to query pPhysicalDeviceCount."); 10970cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } // TODO : Could also flag a warning if re-calling this function in QUERY_DETAILS state 10971bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis else if (instance_data->physical_devices_count != *pPhysicalDeviceCount) { 10972bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis // Having actual count match count from app is not a requirement, so this can be a warning 10973bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis skip_call |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, 10974bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_COUNT_MISMATCH, "DL", 10975bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis "Call to vkEnumeratePhysicalDevices() w/ pPhysicalDeviceCount value %u, but actual count " 10976bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis "supported by this instance is %u.", 10977bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis *pPhysicalDeviceCount, instance_data->physical_devices_count); 10978bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis } 10979bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis instance_data->vkEnumeratePhysicalDevicesState = QUERY_DETAILS; 10980f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski } 10981bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis if (skip_call) { 10982bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis return VK_ERROR_VALIDATION_FAILED_EXT; 10983bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis } 10984bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis VkResult result = instance_data->dispatch_table.EnumeratePhysicalDevices(instance, pPhysicalDeviceCount, pPhysicalDevices); 10985bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis if (NULL == pPhysicalDevices) { 10986bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis instance_data->physical_devices_count = *pPhysicalDeviceCount; 10987cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else if (result == VK_SUCCESS) { // Save physical devices 10988bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++) { 10989bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis auto &phys_device_state = instance_data->physical_device_map[pPhysicalDevices[i]]; 10990bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis phys_device_state.phys_device = pPhysicalDevices[i]; 10991bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis // Init actual features for each physical device 10992bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis instance_data->dispatch_table.GetPhysicalDeviceFeatures(pPhysicalDevices[i], &phys_device_state.features); 10993bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis } 10994bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis } 10995bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis return result; 10996f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski} 10997f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski 1099843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis// Common function to handle validation for GetPhysicalDeviceQueueFamilyProperties & 2KHR version 1099943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic bool ValidateCommonGetPhysicalDeviceQueueFamilyProperties(instance_layer_data *instance_data, 1100043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis PHYSICAL_DEVICE_STATE *pd_state, 1100143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis uint32_t *pQueueFamilyPropertyCount, bool qfp_null, 1100243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis const char *count_var_name, const char *caller_name) { 1100343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis bool skip = false; 1100443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis if (qfp_null) { 1100543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis pd_state->vkGetPhysicalDeviceQueueFamilyPropertiesState = QUERY_COUNT; 1100643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } else { 1100743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis // Verify that for each physical device, this function is called first with NULL pQueueFamilyProperties ptr in order to get 1100843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis // count 1100943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis if (UNCALLED == pd_state->vkGetPhysicalDeviceQueueFamilyPropertiesState) { 1101043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, 1101143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_MISSING_QUERY_COUNT, "DL", 1101243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis "Call sequence has %s() w/ non-NULL " 1101343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis "pQueueFamilyProperties. You should first call %s() w/ " 1101443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis "NULL pQueueFamilyProperties to query pCount.", 1101543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis caller_name, caller_name); 1101643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 1101743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis // Then verify that pCount that is passed in on second call matches what was returned 1101843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis if (pd_state->queueFamilyPropertiesCount != *pQueueFamilyPropertyCount) { 1101943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis // TODO: this is not a requirement of the Valid Usage section for vkGetPhysicalDeviceQueueFamilyProperties, so 1102043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis // provide as warning 1102143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, 1102243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_COUNT_MISMATCH, "DL", 1102343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis "Call to %s() w/ %s value %u, but actual count supported by this physicalDevice is %u.", caller_name, 1102443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis count_var_name, *pQueueFamilyPropertyCount, pd_state->queueFamilyPropertiesCount); 1102543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 1102643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis pd_state->vkGetPhysicalDeviceQueueFamilyPropertiesState = QUERY_DETAILS; 1102743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 1102843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis return skip; 1102943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis} 1103043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis 1103143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic bool PreCallValidateGetPhysicalDeviceQueueFamilyProperties(instance_layer_data *instance_data, 1103243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis PHYSICAL_DEVICE_STATE *pd_state, uint32_t *pCount, 1103343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis VkQueueFamilyProperties *pQueueFamilyProperties) { 1103443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis return ValidateCommonGetPhysicalDeviceQueueFamilyProperties(instance_data, pd_state, pCount, 1103543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis (nullptr == pQueueFamilyProperties), "pCount", 1103643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis "vkGetPhysicalDeviceQueueFamilyProperties()"); 1103743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis} 1103843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis 1103943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic bool PreCallValidateGetPhysicalDeviceQueueFamilyProperties2KHR(instance_layer_data *instance_data, 1104043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis PHYSICAL_DEVICE_STATE *pd_state, 1104143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis uint32_t *pQueueFamilyPropertyCount, 1104243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis VkQueueFamilyProperties2KHR *pQueueFamilyProperties) { 1104343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis return ValidateCommonGetPhysicalDeviceQueueFamilyProperties(instance_data, pd_state, pQueueFamilyPropertyCount, 1104443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis (nullptr == pQueueFamilyProperties), "pQueueFamilyPropertyCount", 1104543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis "vkGetPhysicalDeviceQueueFamilyProperties2KHR()"); 1104643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis} 1104743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis 1104843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis// Common function to update state for GetPhysicalDeviceQueueFamilyProperties & 2KHR version 1104943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic void StateUpdateCommonGetPhysicalDeviceQueueFamilyProperties(PHYSICAL_DEVICE_STATE *pd_state, uint32_t count, 1105043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis VkQueueFamilyProperties2KHR *pQueueFamilyProperties) { 1105143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis if (!pQueueFamilyProperties) { 1105243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis pd_state->queueFamilyPropertiesCount = count; 1105343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } else { // Save queue family properties 1105443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis if (pd_state->queue_family_properties.size() < count) pd_state->queue_family_properties.resize(count); 1105543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis for (uint32_t i = 0; i < count; i++) { 1105643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis pd_state->queue_family_properties[i] = pQueueFamilyProperties[i].queueFamilyProperties; 1105743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 1105843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 1105943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis} 1106043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis 1106143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic void PostCallRecordGetPhysicalDeviceQueueFamilyProperties(PHYSICAL_DEVICE_STATE *pd_state, uint32_t count, 1106243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis VkQueueFamilyProperties *pQueueFamilyProperties) { 1106343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis VkQueueFamilyProperties2KHR *pqfp = nullptr; 1106443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis std::vector<VkQueueFamilyProperties2KHR> qfp; 1106543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis qfp.resize(count); 1106643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis if (pQueueFamilyProperties) { 1106743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis for (uint32_t i = 0; i < count; ++i) { 1106843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis qfp[i].sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2_KHR; 1106943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis qfp[i].pNext = nullptr; 1107043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis qfp[i].queueFamilyProperties = pQueueFamilyProperties[i]; 1107143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 1107243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis pqfp = qfp.data(); 1107343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 1107443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis StateUpdateCommonGetPhysicalDeviceQueueFamilyProperties(pd_state, count, pqfp); 1107543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis} 1107643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis 1107743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic void PostCallRecordGetPhysicalDeviceQueueFamilyProperties2KHR(PHYSICAL_DEVICE_STATE *pd_state, uint32_t count, 1107843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis VkQueueFamilyProperties2KHR *pQueueFamilyProperties) { 1107943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis StateUpdateCommonGetPhysicalDeviceQueueFamilyProperties(pd_state, count, pQueueFamilyProperties); 1108043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis} 1108143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis 11082bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, 11083bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkQueueFamilyProperties *pQueueFamilyProperties) { 1108456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 110859a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto physical_device_state = GetPhysicalDeviceState(instance_data, physicalDevice); 1108643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis assert(physical_device_state); 1108743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis bool skip = 1108843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis PreCallValidateGetPhysicalDeviceQueueFamilyProperties(instance_data, physical_device_state, pCount, pQueueFamilyProperties); 1108943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis if (skip) { 1109043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis return; 1109143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 1109243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis instance_data->dispatch_table.GetPhysicalDeviceQueueFamilyProperties(physicalDevice, pCount, pQueueFamilyProperties); 1109343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis PostCallRecordGetPhysicalDeviceQueueFamilyProperties(physical_device_state, *pCount, pQueueFamilyProperties); 1109443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis} 1109543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis 1109643947a6175e3e942e04d902f4d18928168e2d0dbTobin EhlisVKAPI_ATTR void VKAPI_CALL GetPhysicalDeviceQueueFamilyProperties2KHR(VkPhysicalDevice physicalDevice, 1109743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis uint32_t *pQueueFamilyPropertyCount, 1109843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis VkQueueFamilyProperties2KHR *pQueueFamilyProperties) { 1109956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 111009a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto physical_device_state = GetPhysicalDeviceState(instance_data, physicalDevice); 1110143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis assert(physical_device_state); 1110243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis bool skip = PreCallValidateGetPhysicalDeviceQueueFamilyProperties2KHR(instance_data, physical_device_state, 1110343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis pQueueFamilyPropertyCount, pQueueFamilyProperties); 1110443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis if (skip) { 1110543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis return; 11106cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski } 1110743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis instance_data->dispatch_table.GetPhysicalDeviceQueueFamilyProperties2KHR(physicalDevice, pQueueFamilyPropertyCount, 1110843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis pQueueFamilyProperties); 1110943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis PostCallRecordGetPhysicalDeviceQueueFamilyProperties2KHR(physical_device_state, *pQueueFamilyPropertyCount, 1111043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis pQueueFamilyProperties); 11111cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski} 11112cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski 11113bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskitemplate <typename TCreateInfo, typename FPtr> 11114bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic VkResult CreateSurface(VkInstance instance, TCreateInfo const *pCreateInfo, VkAllocationCallbacks const *pAllocator, 11115bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkSurfaceKHR *pSurface, FPtr fptr) { 1111656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 11117747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11118747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes // Call down the call chain: 11119747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes VkResult result = (instance_data->dispatch_table.*fptr)(instance, pCreateInfo, pAllocator, pSurface); 11120747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11121747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (result == VK_SUCCESS) { 11122747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes std::unique_lock<std::mutex> lock(global_lock); 11123747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->surface_map[*pSurface] = SURFACE_STATE(*pSurface); 11124747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes lock.unlock(); 11125747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes } 11126747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11127747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes return result; 11128747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 11129747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11130747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR void VKAPI_CALL DestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks *pAllocator) { 11131747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes bool skip_call = false; 1113256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 11133747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes std::unique_lock<std::mutex> lock(global_lock); 111349a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto surface_state = GetSurfaceState(instance_data, surface); 11135747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11136747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (surface_state) { 11137747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes // TODO: track swapchains created from this surface. 11138747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->surface_map.erase(surface); 11139747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes } 11140747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes lock.unlock(); 11141747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11142747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (!skip_call) { 11143747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes // Call down the call chain: 11144747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->dispatch_table.DestroySurfaceKHR(instance, surface, pAllocator); 11145747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes } 11146747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 11147747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 111486f2ed666809272002a31b3b4f8adf6581cb41819Norbert NopperVKAPI_ATTR VkResult VKAPI_CALL CreateDisplayPlaneSurfaceKHR(VkInstance instance, const VkDisplaySurfaceCreateInfoKHR *pCreateInfo, 111496f2ed666809272002a31b3b4f8adf6581cb41819Norbert Nopper const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) { 111506f2ed666809272002a31b3b4f8adf6581cb41819Norbert Nopper return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateDisplayPlaneSurfaceKHR); 111516f2ed666809272002a31b3b4f8adf6581cb41819Norbert Nopper} 111526f2ed666809272002a31b3b4f8adf6581cb41819Norbert Nopper 11153747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_ANDROID_KHR 11154747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR *pCreateInfo, 11155747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) { 11156747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateAndroidSurfaceKHR); 11157747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 11158cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_ANDROID_KHR 11159747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11160747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_MIR_KHR 11161747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateMirSurfaceKHR(VkInstance instance, const VkMirSurfaceCreateInfoKHR *pCreateInfo, 11162747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) { 11163747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateMirSurfaceKHR); 11164747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 11165cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_MIR_KHR 11166747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11167747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_WAYLAND_KHR 11168747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateWaylandSurfaceKHR(VkInstance instance, const VkWaylandSurfaceCreateInfoKHR *pCreateInfo, 11169747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) { 11170a9c6cc532ce0ef61d48d1419a96aae51b0e4c64aTobin Ehlis return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateWaylandSurfaceKHR); 11171747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 11172cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_WAYLAND_KHR 11173747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11174747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_WIN32_KHR 11175747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateWin32SurfaceKHR(VkInstance instance, const VkWin32SurfaceCreateInfoKHR *pCreateInfo, 11176747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) { 11177747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateWin32SurfaceKHR); 11178747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 11179cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_WIN32_KHR 11180747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11181747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_XCB_KHR 11182747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateXcbSurfaceKHR(VkInstance instance, const VkXcbSurfaceCreateInfoKHR *pCreateInfo, 11183747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) { 11184747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateXcbSurfaceKHR); 11185747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 11186cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_XCB_KHR 11187747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11188747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_XLIB_KHR 11189747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateXlibSurfaceKHR(VkInstance instance, const VkXlibSurfaceCreateInfoKHR *pCreateInfo, 11190bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) { 11191747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateXlibSurfaceKHR); 11192747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 11193cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_XLIB_KHR 11194747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 1119540921785005eb449ec7c18229f0d84c879708b8aChris ForbesVKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, 1119640921785005eb449ec7c18229f0d84c879708b8aChris Forbes VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) { 1119756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis auto instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 1119840921785005eb449ec7c18229f0d84c879708b8aChris Forbes 1119940921785005eb449ec7c18229f0d84c879708b8aChris Forbes std::unique_lock<std::mutex> lock(global_lock); 112009a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto physical_device_state = GetPhysicalDeviceState(instance_data, physicalDevice); 1120140921785005eb449ec7c18229f0d84c879708b8aChris Forbes lock.unlock(); 1120240921785005eb449ec7c18229f0d84c879708b8aChris Forbes 11203bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto result = 11204bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski instance_data->dispatch_table.GetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, pSurfaceCapabilities); 1120540921785005eb449ec7c18229f0d84c879708b8aChris Forbes 1120640921785005eb449ec7c18229f0d84c879708b8aChris Forbes if (result == VK_SUCCESS) { 1120740921785005eb449ec7c18229f0d84c879708b8aChris Forbes physical_device_state->vkGetPhysicalDeviceSurfaceCapabilitiesKHRState = QUERY_DETAILS; 1120840921785005eb449ec7c18229f0d84c879708b8aChris Forbes physical_device_state->surfaceCapabilities = *pSurfaceCapabilities; 1120940921785005eb449ec7c18229f0d84c879708b8aChris Forbes } 1121040921785005eb449ec7c18229f0d84c879708b8aChris Forbes 1121140921785005eb449ec7c18229f0d84c879708b8aChris Forbes return result; 1121240921785005eb449ec7c18229f0d84c879708b8aChris Forbes} 1121340921785005eb449ec7c18229f0d84c879708b8aChris Forbes 11214418a8711f3301f3027a900bb45daaf0892f4e644Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, 11215418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes VkSurfaceKHR surface, VkBool32 *pSupported) { 1121656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis auto instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 11217418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes std::unique_lock<std::mutex> lock(global_lock); 112189a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto surface_state = GetSurfaceState(instance_data, surface); 11219418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes lock.unlock(); 11220418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes 11221bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto result = 11222bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski instance_data->dispatch_table.GetPhysicalDeviceSurfaceSupportKHR(physicalDevice, queueFamilyIndex, surface, pSupported); 11223418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes 11224418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes if (result == VK_SUCCESS) { 112256569ab421f45f905e69fa7345bda4fe5b87e9045Mark Lobodzinski surface_state->gpu_queue_support[{physicalDevice, queueFamilyIndex}] = (*pSupported != 0); 11226418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes } 11227418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes 11228418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes return result; 11229418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes} 11230418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes 112319e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, 112329e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes uint32_t *pPresentModeCount, 112339e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes VkPresentModeKHR *pPresentModes) { 112349e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes bool skip_call = false; 1123556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis auto instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 112369e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes std::unique_lock<std::mutex> lock(global_lock); 112379e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes // TODO: this isn't quite right. available modes may differ by surface AND physical device. 112389a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto physical_device_state = GetPhysicalDeviceState(instance_data, physicalDevice); 11239bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto &call_state = physical_device_state->vkGetPhysicalDeviceSurfacePresentModesKHRState; 112409e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes 112419e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (pPresentModes) { 112429e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes // Compare the preliminary value of *pPresentModeCount with the value this time: 11243bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto prev_mode_count = (uint32_t)physical_device_state->present_modes.size(); 112449e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes switch (call_state) { 11245cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case UNCALLED: 112469e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes skip_call |= log_msg( 11247bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 11248cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski reinterpret_cast<uint64_t>(physicalDevice), __LINE__, DEVLIMITS_MUST_QUERY_COUNT, "DL", 11249cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkGetPhysicalDeviceSurfacePresentModesKHR() called with non-NULL pPresentModeCount; but no prior positive " 11250cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "value has been seen for pPresentModeCount."); 11251cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 11252cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 11253cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // both query count and query details 11254cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (*pPresentModeCount != prev_mode_count) { 11255cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski skip_call |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, 11256cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 11257cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski reinterpret_cast<uint64_t>(physicalDevice), __LINE__, DEVLIMITS_COUNT_MISMATCH, "DL", 11258cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkGetPhysicalDeviceSurfacePresentModesKHR() called with *pPresentModeCount (%u) that " 11259cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "differs from the value " 11260cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "(%u) that was returned when pPresentModes was NULL.", 11261cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski *pPresentModeCount, prev_mode_count); 11262cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 11263cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 112649e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 112659e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 112669e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes lock.unlock(); 112679e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes 11268cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip_call) return VK_ERROR_VALIDATION_FAILED_EXT; 112699e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes 11270bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto result = instance_data->dispatch_table.GetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, pPresentModeCount, 11271bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pPresentModes); 112729e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes 112739e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (result == VK_SUCCESS || result == VK_INCOMPLETE) { 112749e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes lock.lock(); 112759e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes 112769e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (*pPresentModeCount) { 11277cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (call_state < QUERY_COUNT) call_state = QUERY_COUNT; 112789e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (*pPresentModeCount > physical_device_state->present_modes.size()) 112799e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes physical_device_state->present_modes.resize(*pPresentModeCount); 112809e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 112819e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (pPresentModes) { 11282cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (call_state < QUERY_DETAILS) call_state = QUERY_DETAILS; 112839e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes for (uint32_t i = 0; i < *pPresentModeCount; i++) { 112849e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes physical_device_state->present_modes[i] = pPresentModes[i]; 112859e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 112869e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 112875faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 112885faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes 112895faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes return result; 112905faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes} 112915faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes 112925faa662f6859b01c72d79027abde363d5f10dcd7Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, 112935faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes uint32_t *pSurfaceFormatCount, 112945faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes VkSurfaceFormatKHR *pSurfaceFormats) { 112955faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes bool skip_call = false; 1129656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis auto instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 112975faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes std::unique_lock<std::mutex> lock(global_lock); 112989a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto physical_device_state = GetPhysicalDeviceState(instance_data, physicalDevice); 11299bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto &call_state = physical_device_state->vkGetPhysicalDeviceSurfaceFormatsKHRState; 113005faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes 113015faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (pSurfaceFormats) { 11302bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto prev_format_count = (uint32_t)physical_device_state->surface_formats.size(); 113035faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes 113045faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes switch (call_state) { 11305cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case UNCALLED: 11306cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Since we haven't recorded a preliminary value of *pSurfaceFormatCount, that likely means that the application 11307cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // didn't 11308cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // previously call this function with a NULL value of pSurfaceFormats: 113095faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes skip_call |= log_msg( 11310bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 11311cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski reinterpret_cast<uint64_t>(physicalDevice), __LINE__, DEVLIMITS_MUST_QUERY_COUNT, "DL", 11312cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkGetPhysicalDeviceSurfaceFormatsKHR() called with non-NULL pSurfaceFormatCount; but no prior positive " 11313cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "value has been seen for pSurfaceFormats."); 11314cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 11315cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 11316cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (prev_format_count != *pSurfaceFormatCount) { 11317cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski skip_call |= log_msg( 11318cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, 11319cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, reinterpret_cast<uint64_t>(physicalDevice), __LINE__, 11320cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski DEVLIMITS_COUNT_MISMATCH, "DL", 11321cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkGetPhysicalDeviceSurfaceFormatsKHR() called with non-NULL pSurfaceFormatCount, and with pSurfaceFormats " 11322cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "set " 11323cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "to " 11324cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "a value (%u) that is greater than the value (%u) that was returned when pSurfaceFormatCount was NULL.", 11325cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski *pSurfaceFormatCount, prev_format_count); 11326cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 11327cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 113289e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 113299e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 113305faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes lock.unlock(); 113315faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes 11332cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip_call) return VK_ERROR_VALIDATION_FAILED_EXT; 113339e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes 113345faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes // Call down the call chain: 113355faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes auto result = instance_data->dispatch_table.GetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, pSurfaceFormatCount, 113365faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes pSurfaceFormats); 113375faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes 113385faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (result == VK_SUCCESS || result == VK_INCOMPLETE) { 113395faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes lock.lock(); 113405faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes 113415faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (*pSurfaceFormatCount) { 11342cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (call_state < QUERY_COUNT) call_state = QUERY_COUNT; 113435faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (*pSurfaceFormatCount > physical_device_state->surface_formats.size()) 113445faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes physical_device_state->surface_formats.resize(*pSurfaceFormatCount); 113455faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 113465faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (pSurfaceFormats) { 11347cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (call_state < QUERY_DETAILS) call_state = QUERY_DETAILS; 113485faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes for (uint32_t i = 0; i < *pSurfaceFormatCount; i++) { 113495faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes physical_device_state->surface_formats[i] = pSurfaceFormats[i]; 113505faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 113515faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 113525faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 113539e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes return result; 113549e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes} 113559e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes 11356bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateDebugReportCallbackEXT(VkInstance instance, 11357bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkDebugReportCallbackCreateInfoEXT *pCreateInfo, 11358bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, 11359bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDebugReportCallbackEXT *pMsgCallback) { 1136056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 113619172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes VkResult res = instance_data->dispatch_table.CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback); 113625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == res) { 11363b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 113648860b85a52096f9f9b28616bc37feed505497a54Chris Forbes res = layer_create_msg_callback(instance_data->report_data, false, pCreateInfo, pAllocator, pMsgCallback); 113655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 113665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return res; 113675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 113685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 11369bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT msgCallback, 1137089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator) { 1137156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 113729172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes instance_data->dispatch_table.DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator); 11373b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 113748860b85a52096f9f9b28616bc37feed505497a54Chris Forbes layer_destroy_msg_callback(instance_data->report_data, msgCallback, pAllocator); 113755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 113765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 11377bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, 11378bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDebugReportObjectTypeEXT objType, uint64_t object, size_t location, 11379bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski int32_t msgCode, const char *pLayerPrefix, const char *pMsg) { 1138056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 113819172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes instance_data->dispatch_table.DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg); 113825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 113835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 11384bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) { 11385a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu return util_GetLayerProperties(1, &global_layer, pCount, pProperties); 11386a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu} 11387a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu 11388bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, 11389bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkLayerProperties *pProperties) { 11390a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu return util_GetLayerProperties(1, &global_layer, pCount, pProperties); 11391a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu} 11392a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu 11393bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, 11394bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkExtensionProperties *pProperties) { 11395a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) 11396a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties); 11397a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu 11398a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu return VK_ERROR_LAYER_NOT_PRESENT; 11399a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu} 11400a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu 11401bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName, 11402bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski uint32_t *pCount, VkExtensionProperties *pProperties) { 11403cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(0, NULL, pCount, pProperties); 11404a8f4a23b1e9c068717eda47cc583a93f447c77e3Chia-I Wu 11405a8f4a23b1e9c068717eda47cc583a93f447c77e3Chia-I Wu assert(physicalDevice); 11406a8f4a23b1e9c068717eda47cc583a93f447c77e3Chia-I Wu 1140756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 114089172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes return instance_data->dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties); 1140908939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu} 1141008939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu 11411bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic PFN_vkVoidFunction intercept_core_instance_command(const char *name); 114127ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu 11413bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic PFN_vkVoidFunction intercept_core_device_command(const char *name); 1141480be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu 11415bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic PFN_vkVoidFunction intercept_khr_swapchain_command(const char *name, VkDevice dev); 1141609a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu 11417bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic PFN_vkVoidFunction intercept_khr_surface_command(const char *name, VkInstance instance); 11418747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11419bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic PFN_vkVoidFunction intercept_extension_instance_commands(const char *name, VkInstance instance); 11420b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 1142189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice dev, const char *funcName) { 1142280be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu PFN_vkVoidFunction proc = intercept_core_device_command(funcName); 11423cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (proc) return proc; 1142480be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu 1142580be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu assert(dev); 114265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1142709a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu proc = intercept_khr_swapchain_command(funcName, dev); 11428cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (proc) return proc; 1142909a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu 1143056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(dev), layer_data_map); 114315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 114324a0754042cf090e131e9e769d8a3633c228625beChris Forbes auto &table = dev_data->dispatch_table; 11433cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!table.GetDeviceProcAddr) return nullptr; 114344a0754042cf090e131e9e769d8a3633c228625beChris Forbes return table.GetDeviceProcAddr(dev, funcName); 114355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 114365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1143789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) { 114387ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu PFN_vkVoidFunction proc = intercept_core_instance_command(funcName); 11439cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!proc) proc = intercept_core_device_command(funcName); 11440cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!proc) proc = intercept_khr_swapchain_command(funcName, VK_NULL_HANDLE); 11441cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!proc) proc = intercept_khr_surface_command(funcName, instance); 11442cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (proc) return proc; 114435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 114447ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu assert(instance); 114455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1144656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 114478860b85a52096f9f9b28616bc37feed505497a54Chris Forbes proc = debug_report_get_instance_proc_addr(instance_data->report_data, funcName); 11448cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (proc) return proc; 114495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 11450b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young proc = intercept_extension_instance_commands(funcName, instance); 11451cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (proc) return proc; 11452b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 114534a0754042cf090e131e9e769d8a3633c228625beChris Forbes auto &table = instance_data->dispatch_table; 11454cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!table.GetInstanceProcAddr) return nullptr; 114554a0754042cf090e131e9e769d8a3633c228625beChris Forbes return table.GetInstanceProcAddr(instance, funcName); 114565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 1145708939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu 11458b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark YoungVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetPhysicalDeviceProcAddr(VkInstance instance, const char *funcName) { 11459b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young assert(instance); 11460b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 1146156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 11462b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 11463b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young auto &table = instance_data->dispatch_table; 11464cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!table.GetPhysicalDeviceProcAddr) return nullptr; 11465b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young return table.GetPhysicalDeviceProcAddr(instance, funcName); 11466b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young} 11467b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 11468bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic PFN_vkVoidFunction intercept_core_instance_command(const char *name) { 114697ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu static const struct { 114707ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu const char *name; 114717ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu PFN_vkVoidFunction proc; 114727ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu } core_instance_commands[] = { 11473bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkGetInstanceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr)}, 11474bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vk_layerGetPhysicalDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceProcAddr)}, 11475bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkGetDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr)}, 11476bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkCreateInstance", reinterpret_cast<PFN_vkVoidFunction>(CreateInstance)}, 11477bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkCreateDevice", reinterpret_cast<PFN_vkVoidFunction>(CreateDevice)}, 11478bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkEnumeratePhysicalDevices", reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDevices)}, 11479bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkGetPhysicalDeviceQueueFamilyProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceQueueFamilyProperties)}, 11480bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance)}, 11481bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkEnumerateInstanceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceLayerProperties)}, 11482bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkEnumerateDeviceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceLayerProperties)}, 11483bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkEnumerateInstanceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceExtensionProperties)}, 11484bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkEnumerateDeviceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceExtensionProperties)}, 114857ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu }; 114867ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu 114877ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu for (size_t i = 0; i < ARRAY_SIZE(core_instance_commands); i++) { 11488cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!strcmp(core_instance_commands[i].name, name)) return core_instance_commands[i].proc; 114897ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu } 114907ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu 114917ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu return nullptr; 114927ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu} 114937ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu 11494bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic PFN_vkVoidFunction intercept_core_device_command(const char *name) { 1149580be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu static const struct { 1149680be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu const char *name; 1149780be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu PFN_vkVoidFunction proc; 1149880be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu } core_device_commands[] = { 11499593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkGetDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr)}, 11500593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkQueueSubmit", reinterpret_cast<PFN_vkVoidFunction>(QueueSubmit)}, 11501593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkWaitForFences", reinterpret_cast<PFN_vkVoidFunction>(WaitForFences)}, 11502593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkGetFenceStatus", reinterpret_cast<PFN_vkVoidFunction>(GetFenceStatus)}, 11503593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkQueueWaitIdle", reinterpret_cast<PFN_vkVoidFunction>(QueueWaitIdle)}, 11504593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDeviceWaitIdle", reinterpret_cast<PFN_vkVoidFunction>(DeviceWaitIdle)}, 11505593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkGetDeviceQueue", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceQueue)}, 11506593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance)}, 11507593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyDevice", reinterpret_cast<PFN_vkVoidFunction>(DestroyDevice)}, 11508593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyFence", reinterpret_cast<PFN_vkVoidFunction>(DestroyFence)}, 11509593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkResetFences", reinterpret_cast<PFN_vkVoidFunction>(ResetFences)}, 11510593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroySemaphore", reinterpret_cast<PFN_vkVoidFunction>(DestroySemaphore)}, 11511593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyEvent", reinterpret_cast<PFN_vkVoidFunction>(DestroyEvent)}, 11512593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyQueryPool", reinterpret_cast<PFN_vkVoidFunction>(DestroyQueryPool)}, 11513593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyBuffer", reinterpret_cast<PFN_vkVoidFunction>(DestroyBuffer)}, 11514593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyBufferView", reinterpret_cast<PFN_vkVoidFunction>(DestroyBufferView)}, 11515593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyImage", reinterpret_cast<PFN_vkVoidFunction>(DestroyImage)}, 11516593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyImageView", reinterpret_cast<PFN_vkVoidFunction>(DestroyImageView)}, 11517593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyShaderModule", reinterpret_cast<PFN_vkVoidFunction>(DestroyShaderModule)}, 11518593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyPipeline", reinterpret_cast<PFN_vkVoidFunction>(DestroyPipeline)}, 11519593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyPipelineLayout", reinterpret_cast<PFN_vkVoidFunction>(DestroyPipelineLayout)}, 11520593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroySampler", reinterpret_cast<PFN_vkVoidFunction>(DestroySampler)}, 11521593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyDescriptorSetLayout", reinterpret_cast<PFN_vkVoidFunction>(DestroyDescriptorSetLayout)}, 11522593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(DestroyDescriptorPool)}, 11523593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyFramebuffer", reinterpret_cast<PFN_vkVoidFunction>(DestroyFramebuffer)}, 11524593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyRenderPass", reinterpret_cast<PFN_vkVoidFunction>(DestroyRenderPass)}, 11525593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateBuffer", reinterpret_cast<PFN_vkVoidFunction>(CreateBuffer)}, 11526593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateBufferView", reinterpret_cast<PFN_vkVoidFunction>(CreateBufferView)}, 11527593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateImage", reinterpret_cast<PFN_vkVoidFunction>(CreateImage)}, 11528593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateImageView", reinterpret_cast<PFN_vkVoidFunction>(CreateImageView)}, 11529593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateFence", reinterpret_cast<PFN_vkVoidFunction>(CreateFence)}, 11530593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreatePipelineCache", reinterpret_cast<PFN_vkVoidFunction>(CreatePipelineCache)}, 11531593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyPipelineCache", reinterpret_cast<PFN_vkVoidFunction>(DestroyPipelineCache)}, 11532593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkGetPipelineCacheData", reinterpret_cast<PFN_vkVoidFunction>(GetPipelineCacheData)}, 11533593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkMergePipelineCaches", reinterpret_cast<PFN_vkVoidFunction>(MergePipelineCaches)}, 11534593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateGraphicsPipelines", reinterpret_cast<PFN_vkVoidFunction>(CreateGraphicsPipelines)}, 11535593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateComputePipelines", reinterpret_cast<PFN_vkVoidFunction>(CreateComputePipelines)}, 11536593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateSampler", reinterpret_cast<PFN_vkVoidFunction>(CreateSampler)}, 11537593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateDescriptorSetLayout", reinterpret_cast<PFN_vkVoidFunction>(CreateDescriptorSetLayout)}, 11538593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreatePipelineLayout", reinterpret_cast<PFN_vkVoidFunction>(CreatePipelineLayout)}, 11539593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(CreateDescriptorPool)}, 11540593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkResetDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(ResetDescriptorPool)}, 11541593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkAllocateDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(AllocateDescriptorSets)}, 11542593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkFreeDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(FreeDescriptorSets)}, 11543593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkUpdateDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(UpdateDescriptorSets)}, 11544593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateCommandPool", reinterpret_cast<PFN_vkVoidFunction>(CreateCommandPool)}, 11545593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyCommandPool", reinterpret_cast<PFN_vkVoidFunction>(DestroyCommandPool)}, 11546593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkResetCommandPool", reinterpret_cast<PFN_vkVoidFunction>(ResetCommandPool)}, 11547593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateQueryPool", reinterpret_cast<PFN_vkVoidFunction>(CreateQueryPool)}, 11548593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkAllocateCommandBuffers", reinterpret_cast<PFN_vkVoidFunction>(AllocateCommandBuffers)}, 11549593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkFreeCommandBuffers", reinterpret_cast<PFN_vkVoidFunction>(FreeCommandBuffers)}, 11550593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkBeginCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(BeginCommandBuffer)}, 11551593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkEndCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(EndCommandBuffer)}, 11552593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkResetCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(ResetCommandBuffer)}, 11553593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdBindPipeline", reinterpret_cast<PFN_vkVoidFunction>(CmdBindPipeline)}, 11554593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdSetViewport", reinterpret_cast<PFN_vkVoidFunction>(CmdSetViewport)}, 11555593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdSetScissor", reinterpret_cast<PFN_vkVoidFunction>(CmdSetScissor)}, 11556593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdSetLineWidth", reinterpret_cast<PFN_vkVoidFunction>(CmdSetLineWidth)}, 11557593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdSetDepthBias", reinterpret_cast<PFN_vkVoidFunction>(CmdSetDepthBias)}, 11558593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdSetBlendConstants", reinterpret_cast<PFN_vkVoidFunction>(CmdSetBlendConstants)}, 11559593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdSetDepthBounds", reinterpret_cast<PFN_vkVoidFunction>(CmdSetDepthBounds)}, 11560593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdSetStencilCompareMask", reinterpret_cast<PFN_vkVoidFunction>(CmdSetStencilCompareMask)}, 11561593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdSetStencilWriteMask", reinterpret_cast<PFN_vkVoidFunction>(CmdSetStencilWriteMask)}, 11562593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdSetStencilReference", reinterpret_cast<PFN_vkVoidFunction>(CmdSetStencilReference)}, 11563593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdBindDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(CmdBindDescriptorSets)}, 11564593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdBindVertexBuffers", reinterpret_cast<PFN_vkVoidFunction>(CmdBindVertexBuffers)}, 11565593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdBindIndexBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdBindIndexBuffer)}, 11566593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdDraw", reinterpret_cast<PFN_vkVoidFunction>(CmdDraw)}, 11567593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdDrawIndexed", reinterpret_cast<PFN_vkVoidFunction>(CmdDrawIndexed)}, 11568593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdDrawIndirect", reinterpret_cast<PFN_vkVoidFunction>(CmdDrawIndirect)}, 11569593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdDrawIndexedIndirect", reinterpret_cast<PFN_vkVoidFunction>(CmdDrawIndexedIndirect)}, 11570593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdDispatch", reinterpret_cast<PFN_vkVoidFunction>(CmdDispatch)}, 11571593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdDispatchIndirect", reinterpret_cast<PFN_vkVoidFunction>(CmdDispatchIndirect)}, 11572593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdCopyBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyBuffer)}, 11573593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdCopyImage", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyImage)}, 11574593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdBlitImage", reinterpret_cast<PFN_vkVoidFunction>(CmdBlitImage)}, 11575593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdCopyBufferToImage", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyBufferToImage)}, 11576593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdCopyImageToBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyImageToBuffer)}, 11577593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdUpdateBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdUpdateBuffer)}, 11578593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdFillBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdFillBuffer)}, 11579593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdClearColorImage", reinterpret_cast<PFN_vkVoidFunction>(CmdClearColorImage)}, 11580593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdClearDepthStencilImage", reinterpret_cast<PFN_vkVoidFunction>(CmdClearDepthStencilImage)}, 11581593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdClearAttachments", reinterpret_cast<PFN_vkVoidFunction>(CmdClearAttachments)}, 11582593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdResolveImage", reinterpret_cast<PFN_vkVoidFunction>(CmdResolveImage)}, 11583b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski {"vkGetImageSubresourceLayout", reinterpret_cast<PFN_vkVoidFunction>(GetImageSubresourceLayout) }, 11584593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdSetEvent", reinterpret_cast<PFN_vkVoidFunction>(CmdSetEvent)}, 11585593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdResetEvent", reinterpret_cast<PFN_vkVoidFunction>(CmdResetEvent)}, 11586593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdWaitEvents", reinterpret_cast<PFN_vkVoidFunction>(CmdWaitEvents)}, 11587593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdPipelineBarrier", reinterpret_cast<PFN_vkVoidFunction>(CmdPipelineBarrier)}, 11588593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdBeginQuery", reinterpret_cast<PFN_vkVoidFunction>(CmdBeginQuery)}, 11589593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdEndQuery", reinterpret_cast<PFN_vkVoidFunction>(CmdEndQuery)}, 11590593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdResetQueryPool", reinterpret_cast<PFN_vkVoidFunction>(CmdResetQueryPool)}, 11591593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdCopyQueryPoolResults", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyQueryPoolResults)}, 11592593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdPushConstants", reinterpret_cast<PFN_vkVoidFunction>(CmdPushConstants)}, 11593593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdWriteTimestamp", reinterpret_cast<PFN_vkVoidFunction>(CmdWriteTimestamp)}, 11594593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateFramebuffer", reinterpret_cast<PFN_vkVoidFunction>(CreateFramebuffer)}, 11595593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateShaderModule", reinterpret_cast<PFN_vkVoidFunction>(CreateShaderModule)}, 11596593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateRenderPass", reinterpret_cast<PFN_vkVoidFunction>(CreateRenderPass)}, 11597593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdBeginRenderPass", reinterpret_cast<PFN_vkVoidFunction>(CmdBeginRenderPass)}, 11598593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdNextSubpass", reinterpret_cast<PFN_vkVoidFunction>(CmdNextSubpass)}, 11599593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdEndRenderPass", reinterpret_cast<PFN_vkVoidFunction>(CmdEndRenderPass)}, 11600593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdExecuteCommands", reinterpret_cast<PFN_vkVoidFunction>(CmdExecuteCommands)}, 11601593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkSetEvent", reinterpret_cast<PFN_vkVoidFunction>(SetEvent)}, 11602593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkMapMemory", reinterpret_cast<PFN_vkVoidFunction>(MapMemory)}, 11603593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkUnmapMemory", reinterpret_cast<PFN_vkVoidFunction>(UnmapMemory)}, 11604593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkFlushMappedMemoryRanges", reinterpret_cast<PFN_vkVoidFunction>(FlushMappedMemoryRanges)}, 11605593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkInvalidateMappedMemoryRanges", reinterpret_cast<PFN_vkVoidFunction>(InvalidateMappedMemoryRanges)}, 11606593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkAllocateMemory", reinterpret_cast<PFN_vkVoidFunction>(AllocateMemory)}, 11607593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkFreeMemory", reinterpret_cast<PFN_vkVoidFunction>(FreeMemory)}, 11608593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkBindBufferMemory", reinterpret_cast<PFN_vkVoidFunction>(BindBufferMemory)}, 11609593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkGetBufferMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(GetBufferMemoryRequirements)}, 11610593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkGetImageMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(GetImageMemoryRequirements)}, 11611593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkGetQueryPoolResults", reinterpret_cast<PFN_vkVoidFunction>(GetQueryPoolResults)}, 11612593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkBindImageMemory", reinterpret_cast<PFN_vkVoidFunction>(BindImageMemory)}, 11613593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkQueueBindSparse", reinterpret_cast<PFN_vkVoidFunction>(QueueBindSparse)}, 11614593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateSemaphore", reinterpret_cast<PFN_vkVoidFunction>(CreateSemaphore)}, 11615593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateEvent", reinterpret_cast<PFN_vkVoidFunction>(CreateEvent)}, 1161680be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu }; 1161780be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu 1161880be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu for (size_t i = 0; i < ARRAY_SIZE(core_device_commands); i++) { 11619cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!strcmp(core_device_commands[i].name, name)) return core_device_commands[i].proc; 1162080be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu } 1162180be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu 1162280be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu return nullptr; 1162380be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu} 1162480be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu 11625bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic PFN_vkVoidFunction intercept_khr_swapchain_command(const char *name, VkDevice dev) { 1162609a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu static const struct { 1162709a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu const char *name; 1162809a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu PFN_vkVoidFunction proc; 1162909a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu } khr_swapchain_commands[] = { 11630bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkCreateSwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateSwapchainKHR)}, 11631bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkDestroySwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(DestroySwapchainKHR)}, 11632bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkGetSwapchainImagesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetSwapchainImagesKHR)}, 11633bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkAcquireNextImageKHR", reinterpret_cast<PFN_vkVoidFunction>(AcquireNextImageKHR)}, 11634bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkQueuePresentKHR", reinterpret_cast<PFN_vkVoidFunction>(QueuePresentKHR)}, 1163509a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu }; 11636c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young layer_data *dev_data = nullptr; 1163709a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu 116383f6f8132355ebdae2736b31fc20de2ac60a70310Chia-I Wu if (dev) { 1163956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis dev_data = GetLayerDataPtr(get_dispatch_key(dev), layer_data_map); 11640cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!dev_data->device_extensions.wsi_enabled) return nullptr; 116413f6f8132355ebdae2736b31fc20de2ac60a70310Chia-I Wu } 1164209a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu 1164309a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu for (size_t i = 0; i < ARRAY_SIZE(khr_swapchain_commands); i++) { 11644cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!strcmp(khr_swapchain_commands[i].name, name)) return khr_swapchain_commands[i].proc; 1164509a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu } 1164609a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu 11647c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young if (dev_data) { 11648cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!dev_data->device_extensions.wsi_display_swapchain_enabled) return nullptr; 11649c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young } 11650c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young 11651cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!strcmp("vkCreateSharedSwapchainsKHR", name)) return reinterpret_cast<PFN_vkVoidFunction>(CreateSharedSwapchainsKHR); 11652c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young 1165309a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu return nullptr; 11654747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 11655747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11656bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic PFN_vkVoidFunction intercept_khr_surface_command(const char *name, VkInstance instance) { 11657747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes static const struct { 11658747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes const char *name; 11659747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes PFN_vkVoidFunction proc; 11660747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes bool instance_layer_data::*enable; 11661747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes } khr_surface_commands[] = { 11662747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_ANDROID_KHR 11663747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes {"vkCreateAndroidSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateAndroidSurfaceKHR), 11664bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::androidSurfaceExtensionEnabled}, 11665cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_ANDROID_KHR 11666747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_MIR_KHR 11667747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes {"vkCreateMirSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateMirSurfaceKHR), 11668bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::mirSurfaceExtensionEnabled}, 11669cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_MIR_KHR 11670747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_WAYLAND_KHR 11671747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes {"vkCreateWaylandSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateWaylandSurfaceKHR), 11672bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::waylandSurfaceExtensionEnabled}, 11673cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_WAYLAND_KHR 11674747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_WIN32_KHR 11675747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes {"vkCreateWin32SurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateWin32SurfaceKHR), 11676bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::win32SurfaceExtensionEnabled}, 11677cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_WIN32_KHR 11678747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_XCB_KHR 11679747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes {"vkCreateXcbSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateXcbSurfaceKHR), 11680bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::xcbSurfaceExtensionEnabled}, 11681cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_XCB_KHR 11682747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_XLIB_KHR 11683747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes {"vkCreateXlibSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateXlibSurfaceKHR), 11684bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::xlibSurfaceExtensionEnabled}, 11685cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_XLIB_KHR 11686bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkCreateDisplayPlaneSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateDisplayPlaneSurfaceKHR), 11687bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::displayExtensionEnabled}, 11688747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes {"vkDestroySurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(DestroySurfaceKHR), 11689bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::surfaceExtensionEnabled}, 1169040921785005eb449ec7c18229f0d84c879708b8aChris Forbes {"vkGetPhysicalDeviceSurfaceCapabilitiesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceCapabilitiesKHR), 11691bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::surfaceExtensionEnabled}, 11692418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes {"vkGetPhysicalDeviceSurfaceSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceSupportKHR), 11693bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::surfaceExtensionEnabled}, 116949e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes {"vkGetPhysicalDeviceSurfacePresentModesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfacePresentModesKHR), 11695bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::surfaceExtensionEnabled}, 116965faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes {"vkGetPhysicalDeviceSurfaceFormatsKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceFormatsKHR), 11697bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::surfaceExtensionEnabled}, 11698747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes }; 11699747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11700747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_layer_data *instance_data = nullptr; 11701747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (instance) { 1170256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 11703747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes } 11704747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11705747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes for (size_t i = 0; i < ARRAY_SIZE(khr_surface_commands); i++) { 11706747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (!strcmp(khr_surface_commands[i].name, name)) { 11707cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (instance_data && !(instance_data->*(khr_surface_commands[i].enable))) return nullptr; 11708747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes return khr_surface_commands[i].proc; 11709747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes } 11710747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes } 11711747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11712747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes return nullptr; 1171309a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu} 1171409a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu 1171543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic PFN_vkVoidFunction intercept_extension_instance_commands(const char *name, VkInstance instance) { 1171643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis static const struct { 1171743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis const char *name; 1171843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis PFN_vkVoidFunction proc; 1171943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis bool instance_layer_data::*enable; 1172043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } instance_extension_commands[] = { 1172143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis {"vkGetPhysicalDeviceQueueFamilyProperties2KHR", 1172243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceQueueFamilyProperties2KHR)}, 1172343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis }; 1172443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis 1172543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis for (size_t i = 0; i < ARRAY_SIZE(instance_extension_commands); i++) { 1172643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis if (!strcmp(instance_extension_commands[i].name, name)) { 1172743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis return instance_extension_commands[i].proc; 1172843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 1172943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 1173043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis return nullptr; 1173143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis} 11732b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 11733cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski} // namespace core_validation 11734d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu 11735d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu// vk_layer_logging.h expects these to be defined 11736d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu 11737bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugReportCallbackEXT(VkInstance instance, 11738bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkDebugReportCallbackCreateInfoEXT *pCreateInfo, 11739bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, 11740bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDebugReportCallbackEXT *pMsgCallback) { 1174189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu return core_validation::CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback); 11742d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu} 11743d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu 11744bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT msgCallback, 11745bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator) { 1174689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu core_validation::DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator); 11747d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu} 11748d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu 11749bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL vkDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, 11750bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDebugReportObjectTypeEXT objType, uint64_t object, size_t location, 11751bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski int32_t msgCode, const char *pLayerPrefix, const char *pMsg) { 1175289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu core_validation::DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg); 11753d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu} 11754d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu 11755a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu// loader-layer interface v0, just wrappers since there is only a layer 11756d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu 11757bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, 11758bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkExtensionProperties *pProperties) { 11759a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu return core_validation::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties); 1176008939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu} 1176108939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu 11762bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount, 11763bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkLayerProperties *pProperties) { 11764a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu return core_validation::EnumerateInstanceLayerProperties(pCount, pProperties); 1176508939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu} 1176608939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu 11767bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, 11768bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkLayerProperties *pProperties) { 11769a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu // the layer command handles VK_NULL_HANDLE just fine internally 11770a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu assert(physicalDevice == VK_NULL_HANDLE); 11771a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu return core_validation::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties); 11772d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu} 11773d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu 11774d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I WuVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, 11775d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu const char *pLayerName, uint32_t *pCount, 11776d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu VkExtensionProperties *pProperties) { 11777a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu // the layer command handles VK_NULL_HANDLE just fine internally 11778a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu assert(physicalDevice == VK_NULL_HANDLE); 11779a8f4a23b1e9c068717eda47cc583a93f447c77e3Chia-I Wu return core_validation::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties); 11780d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu} 11781d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu 11782d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I WuVK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) { 1178389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu return core_validation::GetDeviceProcAddr(dev, funcName); 11784d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu} 11785d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu 11786d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I WuVK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) { 1178789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu return core_validation::GetInstanceProcAddr(instance, funcName); 1178808939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu} 11789b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 11790bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance, 11791bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const char *funcName) { 11792b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young return core_validation::GetPhysicalDeviceProcAddr(instance, funcName); 11793b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young} 11794b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 11795b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark YoungVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) { 11796b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young assert(pVersionStruct != NULL); 11797b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT); 11798b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 11799b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young // Fill in the function pointers if our version is at least capable of having the structure contain them. 11800b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young if (pVersionStruct->loaderLayerInterfaceVersion >= 2) { 11801b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr; 11802b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr; 11803b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young pVersionStruct->pfnGetPhysicalDeviceProcAddr = vk_layerGetPhysicalDeviceProcAddr; 11804b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young } 11805b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 11806b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young if (pVersionStruct->loaderLayerInterfaceVersion < CURRENT_LOADER_LAYER_INTERFACE_VERSION) { 11807b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young core_validation::loader_layer_if_version = pVersionStruct->loaderLayerInterfaceVersion; 11808b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young } else if (pVersionStruct->loaderLayerInterfaceVersion > CURRENT_LOADER_LAYER_INTERFACE_VERSION) { 11809b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young pVersionStruct->loaderLayerInterfaceVersion = CURRENT_LOADER_LAYER_INTERFACE_VERSION; 11810b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young } 11811b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 11812b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young return VK_SUCCESS; 11813b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young} 11814