core_validation.cpp revision e659c986db0f3146726d6c744c75772316c3e0c6
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 7283a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// SetMemBinding is used to establish immutable, non-sparse binding between a single image/buffer object and memory object. 7293a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// Corresponding valid usage checks are in ValidateSetMemBinding(). 730c18f059542c30f6b37f8a654df020be38adfade6Cort Strattonstatic void SetMemBinding(layer_data *dev_data, VkDeviceMemory mem, uint64_t handle, VkDebugReportObjectTypeEXT type, 731888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis const char *apiName) { 732c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton if (mem != VK_NULL_HANDLE) { 733c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton BINDABLE *mem_binding = GetObjectMemBinding(dev_data, handle, type); 734c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton assert(mem_binding); 735c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton DEVICE_MEM_INFO *mem_info = GetMemObjInfo(dev_data, mem); 736c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton if (mem_info) { 737c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton mem_info->obj_bindings.insert({handle, type}); 738c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton // For image objects, make sure default memory state is correctly set 739c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton // TODO : What's the best/correct way to handle this? 740c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton if (VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT == type) { 741c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton auto const image_state = GetImageState(dev_data, VkImage(handle)); 742c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton if (image_state) { 743c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton VkImageCreateInfo ici = image_state->createInfo; 744c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton if (ici.usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) { 745c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton // TODO:: More memory state transition stuff. 746c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton } 747c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton } 748c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton } 749c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton mem_binding->binding.mem = mem; 750c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton } 751c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton } 752c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton} 7533a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton 7543a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// Valid usage checks for a call to SetMemBinding(). 7553a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// For NULL mem case, output warning 7563a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// Make sure given object is in global object map 7573a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// IF a previous binding existed, output validation error 7583a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// Otherwise, add reference from objectInfo to memoryInfo 7593a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// Add reference off of objInfo 7603a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// TODO: We may need to refactor or pass in multiple valid usage statements to handle multiple valid usage conditions. 761c18f059542c30f6b37f8a654df020be38adfade6Cort Strattonstatic bool ValidateSetMemBinding(layer_data *dev_data, VkDeviceMemory mem, uint64_t handle, VkDebugReportObjectTypeEXT type, 762c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton const char *apiName) { 76383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 764f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis // It's an error to bind an object to NULL memory 765d3876b4ff7c293a14f73fe3622513d1fa91bf2d0Jeremy Hayes if (mem != VK_NULL_HANDLE) { 766f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis BINDABLE *mem_binding = GetObjectMemBinding(dev_data, handle, type); 767888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis assert(mem_binding); 76810ffe2d353eaff714ed92a2835af77d8b5042d31Cort if (mem_binding->sparse) { 76910ffe2d353eaff714ed92a2835af77d8b5042d31Cort UNIQUE_VALIDATION_ERROR_CODE error_code = VALIDATION_ERROR_00804; 77010ffe2d353eaff714ed92a2835af77d8b5042d31Cort const char *handle_type = "IMAGE"; 77174300755ed9ec780d6073af71e47f201217008d6Cort Stratton if (strcmp(apiName, "vkBindBufferMemory()") == 0) { 77210ffe2d353eaff714ed92a2835af77d8b5042d31Cort error_code = VALIDATION_ERROR_00792; 77310ffe2d353eaff714ed92a2835af77d8b5042d31Cort handle_type = "BUFFER"; 77410ffe2d353eaff714ed92a2835af77d8b5042d31Cort } else { 77574300755ed9ec780d6073af71e47f201217008d6Cort Stratton assert(strcmp(apiName, "vkBindImageMemory()") == 0); 77610ffe2d353eaff714ed92a2835af77d8b5042d31Cort } 77710ffe2d353eaff714ed92a2835af77d8b5042d31Cort skip_call |= 77810ffe2d353eaff714ed92a2835af77d8b5042d31Cort log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 77910ffe2d353eaff714ed92a2835af77d8b5042d31Cort reinterpret_cast<uint64_t &>(mem), __LINE__, error_code, "MEM", 78010ffe2d353eaff714ed92a2835af77d8b5042d31Cort "In %s, attempting to bind memory (0x%" PRIxLEAST64 ") to object (0x%" PRIxLEAST64 78110ffe2d353eaff714ed92a2835af77d8b5042d31Cort ") which was created with sparse memory flags (VK_%s_CREATE_SPARSE_*_BIT). %s", 78210ffe2d353eaff714ed92a2835af77d8b5042d31Cort apiName, reinterpret_cast<uint64_t &>(mem), handle, handle_type, validation_error_map[error_code]); 78310ffe2d353eaff714ed92a2835af77d8b5042d31Cort } 7849a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *mem_info = GetMemObjInfo(dev_data, mem); 785888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis if (mem_info) { 7869a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *prev_binding = GetMemObjInfo(dev_data, mem_binding->binding.mem); 787888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis if (prev_binding) { 78898c2a17e1a549df84f4239f619bc0955f632cb43Cort UNIQUE_VALIDATION_ERROR_CODE error_code = VALIDATION_ERROR_00803; 78974300755ed9ec780d6073af71e47f201217008d6Cort Stratton if (strcmp(apiName, "vkBindBufferMemory()") == 0) { 79098c2a17e1a549df84f4239f619bc0955f632cb43Cort error_code = VALIDATION_ERROR_00791; 79198c2a17e1a549df84f4239f619bc0955f632cb43Cort } else { 79274300755ed9ec780d6073af71e47f201217008d6Cort Stratton assert(strcmp(apiName, "vkBindImageMemory()") == 0); 79398c2a17e1a549df84f4239f619bc0955f632cb43Cort } 794888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis skip_call |= 795888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 79698c2a17e1a549df84f4239f619bc0955f632cb43Cort reinterpret_cast<uint64_t &>(mem), __LINE__, error_code, "MEM", 797888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis "In %s, attempting to bind memory (0x%" PRIxLEAST64 ") to object (0x%" PRIxLEAST64 79898c2a17e1a549df84f4239f619bc0955f632cb43Cort ") which has already been bound to mem object 0x%" PRIxLEAST64 ". %s", 79998c2a17e1a549df84f4239f619bc0955f632cb43Cort apiName, reinterpret_cast<uint64_t &>(mem), handle, reinterpret_cast<uint64_t &>(prev_binding->mem), 80098c2a17e1a549df84f4239f619bc0955f632cb43Cort validation_error_map[error_code]); 801f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis } else if (mem_binding->binding.mem == MEMORY_UNBOUND) { 802888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis skip_call |= 803888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 804888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis reinterpret_cast<uint64_t &>(mem), __LINE__, MEMTRACK_REBIND_OBJECT, "MEM", 805888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis "In %s, attempting to bind memory (0x%" PRIxLEAST64 ") to object (0x%" PRIxLEAST64 806888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis ") which was previous bound to memory that has since been freed. Memory bindings are immutable in " 807888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis "Vulkan so this attempt to bind to new memory is not allowed.", 808888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis apiName, reinterpret_cast<uint64_t &>(mem), handle); 8095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 81283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis return skip_call; 8135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 8145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// For NULL mem case, clear any previous binding Else... 8165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Make sure given object is in its object map 8175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// IF a previous binding existed, update binding 8185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Add reference from objectInfo to memoryInfo 8195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Add reference off of object's binding info 8200a1ce3dfd81c9f4efbe46f5ba5ddaea70bc4aa61Chris Forbes// Return VK_TRUE if addition is successful, VK_FALSE otherwise 821f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlisstatic bool SetSparseMemBinding(layer_data *dev_data, MEM_BINDING binding, uint64_t handle, VkDebugReportObjectTypeEXT type, 822f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis const char *apiName) { 82383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = VK_FALSE; 8245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Handle NULL case separately, just clear previous binding & decrement reference 825f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis if (binding.mem == VK_NULL_HANDLE) { 826f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis // TODO : This should cause the range of the resource to be unbound according to spec 8275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 828f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis BINDABLE *mem_binding = GetObjectMemBinding(dev_data, handle, type); 829f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis assert(mem_binding); 830f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis assert(mem_binding->sparse); 8319a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *mem_info = GetMemObjInfo(dev_data, binding.mem); 832f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis if (mem_info) { 833f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis mem_info->obj_bindings.insert({handle, type}); 8342e415b757c1e43fda35311aad026af8d5c96681cTobin Ehlis // Need to set mem binding for this object 835f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis mem_binding->sparse_bindings.insert(binding); 8365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 83883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis return skip_call; 839caf05e0db4959ae196ab34b024f352d9c0326870Tobin Ehlis} 840caf05e0db4959ae196ab34b024f352d9c0326870Tobin Ehlis 8415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Return a string representation of CMD_TYPE enum 8425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic string cmdTypeToString(CMD_TYPE cmd) { 8435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis switch (cmd) { 844cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_BINDPIPELINE: 845cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_BINDPIPELINE"; 846cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_BINDPIPELINEDELTA: 847cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_BINDPIPELINEDELTA"; 848cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETVIEWPORTSTATE: 849cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_SETVIEWPORTSTATE"; 850cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETLINEWIDTHSTATE: 851cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_SETLINEWIDTHSTATE"; 852cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETDEPTHBIASSTATE: 853cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_SETDEPTHBIASSTATE"; 854cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETBLENDSTATE: 855cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_SETBLENDSTATE"; 856cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETDEPTHBOUNDSSTATE: 857cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_SETDEPTHBOUNDSSTATE"; 858cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETSTENCILREADMASKSTATE: 859cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_SETSTENCILREADMASKSTATE"; 860cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETSTENCILWRITEMASKSTATE: 861cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_SETSTENCILWRITEMASKSTATE"; 862cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETSTENCILREFERENCESTATE: 863cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_SETSTENCILREFERENCESTATE"; 864cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_BINDDESCRIPTORSETS: 865cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_BINDDESCRIPTORSETS"; 866cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_BINDINDEXBUFFER: 867cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_BINDINDEXBUFFER"; 868cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_BINDVERTEXBUFFER: 869cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_BINDVERTEXBUFFER"; 870cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_DRAW: 871cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_DRAW"; 872cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_DRAWINDEXED: 873cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_DRAWINDEXED"; 874cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_DRAWINDIRECT: 875cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_DRAWINDIRECT"; 876cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_DRAWINDEXEDINDIRECT: 877cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_DRAWINDEXEDINDIRECT"; 878cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_DISPATCH: 879cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_DISPATCH"; 880cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_DISPATCHINDIRECT: 881cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_DISPATCHINDIRECT"; 882cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_COPYBUFFER: 883cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_COPYBUFFER"; 884cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_COPYIMAGE: 885cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_COPYIMAGE"; 886cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_BLITIMAGE: 887cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_BLITIMAGE"; 888cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_COPYBUFFERTOIMAGE: 889cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_COPYBUFFERTOIMAGE"; 890cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_COPYIMAGETOBUFFER: 891cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_COPYIMAGETOBUFFER"; 892cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_CLONEIMAGEDATA: 893cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_CLONEIMAGEDATA"; 894cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_UPDATEBUFFER: 895cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_UPDATEBUFFER"; 896cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_FILLBUFFER: 897cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_FILLBUFFER"; 898cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_CLEARCOLORIMAGE: 899cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_CLEARCOLORIMAGE"; 900cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_CLEARATTACHMENTS: 901cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_CLEARCOLORATTACHMENT"; 902cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_CLEARDEPTHSTENCILIMAGE: 903cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_CLEARDEPTHSTENCILIMAGE"; 904cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_RESOLVEIMAGE: 905cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_RESOLVEIMAGE"; 906cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETEVENT: 907cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_SETEVENT"; 908cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_RESETEVENT: 909cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_RESETEVENT"; 910cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_WAITEVENTS: 911cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_WAITEVENTS"; 912cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_PIPELINEBARRIER: 913cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_PIPELINEBARRIER"; 914cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_BEGINQUERY: 915cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_BEGINQUERY"; 916cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_ENDQUERY: 917cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_ENDQUERY"; 918cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_RESETQUERYPOOL: 919cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_RESETQUERYPOOL"; 920cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_COPYQUERYPOOLRESULTS: 921cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_COPYQUERYPOOLRESULTS"; 922cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_WRITETIMESTAMP: 923cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_WRITETIMESTAMP"; 924cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_INITATOMICCOUNTERS: 925cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_INITATOMICCOUNTERS"; 926cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_LOADATOMICCOUNTERS: 927cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_LOADATOMICCOUNTERS"; 928cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SAVEATOMICCOUNTERS: 929cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_SAVEATOMICCOUNTERS"; 930cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_BEGINRENDERPASS: 931cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_BEGINRENDERPASS"; 932cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_ENDRENDERPASS: 933cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_ENDRENDERPASS"; 934cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 935cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "UNKNOWN"; 9365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 9385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// SPIRV utility functions 9405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic void build_def_index(shader_module *module) { 9415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto insn : *module) { 9425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis switch (insn.opcode()) { 943cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Types 944cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeVoid: 945cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeBool: 946cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeInt: 947cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeFloat: 948cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeVector: 949cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeMatrix: 950cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeImage: 951cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeSampler: 952cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeSampledImage: 953cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeArray: 954cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeRuntimeArray: 955cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeStruct: 956cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeOpaque: 957cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypePointer: 958cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeFunction: 959cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeEvent: 960cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeDeviceEvent: 961cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeReserveId: 962cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeQueue: 963cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypePipe: 964cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski module->def_index[insn.word(1)] = insn.offset(); 965cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 9665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 967cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Fixed constants 968cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpConstantTrue: 969cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpConstantFalse: 970cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpConstant: 971cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpConstantComposite: 972cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpConstantSampler: 973cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpConstantNull: 974cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski module->def_index[insn.word(2)] = insn.offset(); 975cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 9765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 977cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Specialization constants 978cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpSpecConstantTrue: 979cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpSpecConstantFalse: 980cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpSpecConstant: 981cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpSpecConstantComposite: 982cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpSpecConstantOp: 983cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski module->def_index[insn.word(2)] = insn.offset(); 984cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 9855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 986cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Variables 987cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpVariable: 988cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski module->def_index[insn.word(2)] = insn.offset(); 989cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 9905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 991cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Functions 992cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpFunction: 993cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski module->def_index[insn.word(2)] = insn.offset(); 994cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 9955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 996cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 997cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // We don't care about any other defs for now. 998cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 9995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 10005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 10015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 10025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic spirv_inst_iter find_entrypoint(shader_module *src, char const *name, VkShaderStageFlagBits stageBits) { 10045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto insn : *src) { 10055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.opcode() == spv::OpEntryPoint) { 10065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto entrypointName = (char const *)&insn.word(3); 10075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto entrypointStageBits = 1u << insn.word(1); 10085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!strcmp(entrypointName, name) && (entrypointStageBits & stageBits)) { 10105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return insn; 10115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 10125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 10135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 10145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return src->end(); 10165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 10175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic char const *storage_class_name(unsigned sc) { 10195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis switch (sc) { 1020cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassInput: 1021cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "input"; 1022cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassOutput: 1023cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "output"; 1024cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassUniformConstant: 1025cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "const uniform"; 1026cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassUniform: 1027cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "uniform"; 1028cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassWorkgroup: 1029cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "workgroup local"; 1030cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassCrossWorkgroup: 1031cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "workgroup global"; 1032cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassPrivate: 1033cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "private global"; 1034cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassFunction: 1035cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "function"; 1036cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassGeneric: 1037cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "generic"; 1038cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassAtomicCounter: 1039cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "atomic counter"; 1040cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassImage: 1041cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "image"; 1042cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassPushConstant: 1043cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "push constant"; 1044cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 1045cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "unknown"; 10465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 10475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 10485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 104925002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// Get the value of an integral constant 10505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisunsigned get_constant_value(shader_module const *src, unsigned id) { 10515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto value = src->get_def(id); 10525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(value != src->end()); 10535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (value.opcode() != spv::OpConstant) { 105525002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // TODO: Either ensure that the specialization transform is already performed on a module we're 105625002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // considering here, OR -- specialize on the fly now. 10575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return 1; 10585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 10595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return value.word(3); 10615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 10625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10639ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbesstatic void describe_type_inner(std::ostringstream &ss, shader_module const *src, unsigned type) { 10645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto insn = src->get_def(type); 10655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(insn != src->end()); 10665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis switch (insn.opcode()) { 1068cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeBool: 1069cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << "bool"; 1070cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1071cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeInt: 1072cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << (insn.word(3) ? 's' : 'u') << "int" << insn.word(2); 1073cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1074cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeFloat: 1075cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << "float" << insn.word(2); 1076cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1077cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeVector: 1078cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << "vec" << insn.word(3) << " of "; 1079cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski describe_type_inner(ss, src, insn.word(2)); 1080cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1081cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeMatrix: 1082cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << "mat" << insn.word(3) << " of "; 1083cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski describe_type_inner(ss, src, insn.word(2)); 1084cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1085cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeArray: 1086cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << "arr[" << get_constant_value(src, insn.word(3)) << "] of "; 1087cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski describe_type_inner(ss, src, insn.word(2)); 1088cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1089cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypePointer: 1090cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << "ptr to " << storage_class_name(insn.word(2)) << " "; 1091cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski describe_type_inner(ss, src, insn.word(3)); 1092cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1093cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeStruct: { 1094cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << "struct of ("; 1095cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski for (unsigned i = 2; i < insn.len(); i++) { 1096cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski describe_type_inner(ss, src, insn.word(i)); 1097cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (i == insn.len() - 1) { 1098cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << ")"; 1099cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else { 1100cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << ", "; 1101cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 11029ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes } 1103cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 11045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 1105cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeSampler: 1106cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << "sampler"; 1107cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1108cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeSampledImage: 1109cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << "sampler+"; 1110cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski describe_type_inner(ss, src, insn.word(2)); 1111cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1112cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeImage: 1113cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << "image(dim=" << insn.word(3) << ", sampled=" << insn.word(7) << ")"; 1114cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1115cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 1116cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << "oddtype"; 1117cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 11185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 11195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 11205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 11219ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbesstatic std::string describe_type(shader_module const *src, unsigned type) { 11229ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes std::ostringstream ss; 11239ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes describe_type_inner(ss, src, type); 11249ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes return ss.str(); 11259ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes} 11269ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes 1127bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic bool is_narrow_numeric_type(spirv_inst_iter type) { 1128cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (type.opcode() != spv::OpTypeInt && type.opcode() != spv::OpTypeFloat) return false; 112937576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes return type.word(2) < 64; 113037576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes} 113137576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes 1132bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic bool types_match(shader_module const *a, shader_module const *b, unsigned a_type, unsigned b_type, bool a_arrayed, 1133bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski bool b_arrayed, bool relaxed) { 113425002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Walk two type trees together, and complain about differences 11355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto a_insn = a->get_def(a_type); 11365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto b_insn = b->get_def(b_type); 11375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(a_insn != a->end()); 11385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(b_insn != b->end()); 11395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 11407c755c8aca6857046df9516d8336416165969cb9Chris Forbes if (a_arrayed && a_insn.opcode() == spv::OpTypeArray) { 114137576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes return types_match(a, b, a_insn.word(2), b_type, false, b_arrayed, relaxed); 11427c755c8aca6857046df9516d8336416165969cb9Chris Forbes } 11437c755c8aca6857046df9516d8336416165969cb9Chris Forbes 11445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (b_arrayed && b_insn.opcode() == spv::OpTypeArray) { 114525002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // We probably just found the extra level of arrayness in b_type: compare the type inside it to a_type 114637576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes return types_match(a, b, a_type, b_insn.word(2), a_arrayed, false, relaxed); 114737576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes } 114837576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes 114937576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes if (a_insn.opcode() == spv::OpTypeVector && relaxed && is_narrow_numeric_type(b_insn)) { 115037576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes return types_match(a, b, a_insn.word(2), b_type, a_arrayed, b_arrayed, false); 11515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 11525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 11535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (a_insn.opcode() != b_insn.opcode()) { 11545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 11555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 11565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 11577c755c8aca6857046df9516d8336416165969cb9Chris Forbes if (a_insn.opcode() == spv::OpTypePointer) { 115825002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Match on pointee type. storage class is expected to differ 115937576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes return types_match(a, b, a_insn.word(3), b_insn.word(3), a_arrayed, b_arrayed, relaxed); 11607c755c8aca6857046df9516d8336416165969cb9Chris Forbes } 11617c755c8aca6857046df9516d8336416165969cb9Chris Forbes 11627c755c8aca6857046df9516d8336416165969cb9Chris Forbes if (a_arrayed || b_arrayed) { 116325002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // If we havent resolved array-of-verts by here, we're not going to. 11647c755c8aca6857046df9516d8336416165969cb9Chris Forbes return false; 11657c755c8aca6857046df9516d8336416165969cb9Chris Forbes } 11667c755c8aca6857046df9516d8336416165969cb9Chris Forbes 11675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis switch (a_insn.opcode()) { 1168cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeBool: 1169cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return true; 1170cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeInt: 1171cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Match on width, signedness 1172cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return a_insn.word(2) == b_insn.word(2) && a_insn.word(3) == b_insn.word(3); 1173cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeFloat: 1174cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Match on width 1175cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return a_insn.word(2) == b_insn.word(2); 1176cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeVector: 1177cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Match on element type, count. 1178cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!types_match(a, b, a_insn.word(2), b_insn.word(2), a_arrayed, b_arrayed, false)) return false; 1179cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (relaxed && is_narrow_numeric_type(a->get_def(a_insn.word(2)))) { 1180cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return a_insn.word(3) >= b_insn.word(3); 1181cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else { 1182cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return a_insn.word(3) == b_insn.word(3); 11835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 1184cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeMatrix: 1185cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Match on element type, count. 1186cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return types_match(a, b, a_insn.word(2), b_insn.word(2), a_arrayed, b_arrayed, false) && 1187cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski a_insn.word(3) == b_insn.word(3); 1188cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeArray: 1189cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Match on element type, count. these all have the same layout. we don't get here if b_arrayed. This differs from 1190cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // vector & matrix types in that the array size is the id of a constant instruction, * not a literal within OpTypeArray 1191cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return types_match(a, b, a_insn.word(2), b_insn.word(2), a_arrayed, b_arrayed, false) && 1192cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski get_constant_value(a, a_insn.word(3)) == get_constant_value(b, b_insn.word(3)); 1193cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeStruct: 1194cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Match on all element types 1195cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski { 1196cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (a_insn.len() != b_insn.len()) { 1197cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return false; // Structs cannot match if member counts differ 1198cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 11995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1200cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski for (unsigned i = 2; i < a_insn.len(); i++) { 1201cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!types_match(a, b, a_insn.word(i), b_insn.word(i), a_arrayed, b_arrayed, false)) { 1202cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return false; 1203cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 1204cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 1205cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski 1206cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return true; 1207cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 1208cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 1209cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Remaining types are CLisms, or may not appear in the interfaces we are interested in. Just claim no match. 1210cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return false; 12115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 12125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 12135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 12145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic int value_or_default(std::unordered_map<unsigned, unsigned> const &map, unsigned id, int def) { 12155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto it = map.find(id); 12165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (it == map.end()) 12175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return def; 12185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis else 12195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return it->second; 12205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 12215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 12225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic unsigned get_locations_consumed_by_type(shader_module const *src, unsigned type, bool strip_array_level) { 12235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto insn = src->get_def(type); 12245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(insn != src->end()); 12255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 12265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis switch (insn.opcode()) { 1227cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypePointer: 1228cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // See through the ptr -- this is only ever at the toplevel for graphics shaders we're never actually passing 1229cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // pointers around. 1230cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return get_locations_consumed_by_type(src, insn.word(3), strip_array_level); 1231cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeArray: 1232cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (strip_array_level) { 1233cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return get_locations_consumed_by_type(src, insn.word(2), false); 1234cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else { 1235cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return get_constant_value(src, insn.word(3)) * get_locations_consumed_by_type(src, insn.word(2), false); 1236cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 1237cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeMatrix: 1238cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Num locations is the dimension * element size 1239cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return insn.word(3) * get_locations_consumed_by_type(src, insn.word(2), false); 1240cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeVector: { 1241cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski auto scalar_type = src->get_def(insn.word(2)); 1242cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski auto bit_width = 1243cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski (scalar_type.opcode() == spv::OpTypeInt || scalar_type.opcode() == spv::OpTypeFloat) ? scalar_type.word(2) : 32; 1244cc52143fc093e1e62d2dacc4abc3966e04b6f6d6Chris Forbes 1245cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Locations are 128-bit wide; 3- and 4-component vectors of 64 bit types require two. 1246cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return (bit_width * insn.word(3) + 127) / 128; 1247cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 1248cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 1249cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Everything else is just 1. 1250cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return 1; 12515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1252cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // TODO: extend to handle 64bit scalar types, whose vectors may need multiple locations. 12535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 12545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 12555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1256c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbesstatic unsigned get_locations_consumed_by_format(VkFormat format) { 1257c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes switch (format) { 1258cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64G64B64A64_SFLOAT: 1259cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64G64B64A64_SINT: 1260cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64G64B64A64_UINT: 1261cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64G64B64_SFLOAT: 1262cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64G64B64_SINT: 1263cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64G64B64_UINT: 1264cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return 2; 1265cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 1266cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return 1; 1267c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes } 1268c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes} 1269c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes 12705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlistypedef std::pair<unsigned, unsigned> location_t; 12715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlistypedef std::pair<unsigned, unsigned> descriptor_slot_t; 12725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 12735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstruct interface_var { 12745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t id; 12755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t type_id; 12765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t offset; 1277b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes bool is_patch; 1278fff9393206f66a154438e16fa0562c989f425498Chris Forbes bool is_block_member; 1279b0436668e6594b8528e96de7bed208399fb2431dChris Forbes bool is_relaxed_precision; 128025002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // TODO: collect the name, too? Isn't required to be present. 12815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}; 12825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1283031261d21af8907953dd763398ce9a23e65b8749Chris Forbesstruct shader_stage_attributes { 1284031261d21af8907953dd763398ce9a23e65b8749Chris Forbes char const *const name; 1285031261d21af8907953dd763398ce9a23e65b8749Chris Forbes bool arrayed_input; 1286031261d21af8907953dd763398ce9a23e65b8749Chris Forbes bool arrayed_output; 1287031261d21af8907953dd763398ce9a23e65b8749Chris Forbes}; 1288031261d21af8907953dd763398ce9a23e65b8749Chris Forbes 1289031261d21af8907953dd763398ce9a23e65b8749Chris Forbesstatic shader_stage_attributes shader_stage_attribs[] = { 1290bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vertex shader", false, false}, {"tessellation control shader", true, true}, {"tessellation evaluation shader", true, false}, 1291bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"geometry shader", true, false}, {"fragment shader", false, false}, 1292031261d21af8907953dd763398ce9a23e65b8749Chris Forbes}; 1293031261d21af8907953dd763398ce9a23e65b8749Chris Forbes 12945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic spirv_inst_iter get_struct_type(shader_module const *src, spirv_inst_iter def, bool is_array_of_verts) { 12955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis while (true) { 12965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (def.opcode() == spv::OpTypePointer) { 12975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis def = src->get_def(def.word(3)); 12985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (def.opcode() == spv::OpTypeArray && is_array_of_verts) { 12995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis def = src->get_def(def.word(2)); 13005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis is_array_of_verts = false; 13015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (def.opcode() == spv::OpTypeStruct) { 13025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return def; 13035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 13045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return src->end(); 13055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 13085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1309bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic void collect_interface_block_members(shader_module const *src, std::map<location_t, interface_var> *out, 13105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_map<unsigned, unsigned> const &blocks, bool is_array_of_verts, 1311b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes uint32_t id, uint32_t type_id, bool is_patch) { 131225002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Walk down the type_id presented, trying to determine whether it's actually an interface block. 1313031261d21af8907953dd763398ce9a23e65b8749Chris Forbes auto type = get_struct_type(src, src->get_def(type_id), is_array_of_verts && !is_patch); 13145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (type == src->end() || blocks.find(type.word(1)) == blocks.end()) { 131525002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // This isn't an interface block. 13165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return; 13175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 13195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_map<unsigned, unsigned> member_components; 13205b9f2047984d6ca10d89a35ba8a2ebe0fa6bff69Chris Forbes std::unordered_map<unsigned, unsigned> member_relaxed_precision; 13215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 132225002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Walk all the OpMemberDecorate for type's result id -- first pass, collect components. 13235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto insn : *src) { 13245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.opcode() == spv::OpMemberDecorate && insn.word(1) == type.word(1)) { 13255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned member_index = insn.word(2); 13265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 13275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.word(3) == spv::DecorationComponent) { 13285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned component = insn.word(4); 13295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis member_components[member_index] = component; 13305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13315b9f2047984d6ca10d89a35ba8a2ebe0fa6bff69Chris Forbes 13325b9f2047984d6ca10d89a35ba8a2ebe0fa6bff69Chris Forbes if (insn.word(3) == spv::DecorationRelaxedPrecision) { 13335b9f2047984d6ca10d89a35ba8a2ebe0fa6bff69Chris Forbes member_relaxed_precision[member_index] = 1; 13345b9f2047984d6ca10d89a35ba8a2ebe0fa6bff69Chris Forbes } 13355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 133825002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Second pass -- produce the output, from Location decorations 13395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto insn : *src) { 13405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.opcode() == spv::OpMemberDecorate && insn.word(1) == type.word(1)) { 13415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned member_index = insn.word(2); 13425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned member_type_id = type.word(2 + member_index); 13435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 13445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.word(3) == spv::DecorationLocation) { 13455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned location = insn.word(4); 13465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned num_locations = get_locations_consumed_by_type(src, member_type_id, false); 13475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto component_it = member_components.find(member_index); 13485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned component = component_it == member_components.end() ? 0 : component_it->second; 13495b9f2047984d6ca10d89a35ba8a2ebe0fa6bff69Chris Forbes bool is_relaxed_precision = member_relaxed_precision.find(member_index) != member_relaxed_precision.end(); 13505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 13515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (unsigned int offset = 0; offset < num_locations; offset++) { 1352b0436668e6594b8528e96de7bed208399fb2431dChris Forbes interface_var v = {}; 13535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis v.id = id; 135425002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // TODO: member index in interface_var too? 13555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis v.type_id = member_type_id; 13565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis v.offset = offset; 1357b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes v.is_patch = is_patch; 1358fff9393206f66a154438e16fa0562c989f425498Chris Forbes v.is_block_member = true; 13595b9f2047984d6ca10d89a35ba8a2ebe0fa6bff69Chris Forbes v.is_relaxed_precision = is_relaxed_precision; 13603a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes (*out)[std::make_pair(location + offset, component)] = v; 13615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 13665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1367bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic std::map<location_t, interface_var> collect_interface_by_location(shader_module const *src, spirv_inst_iter entrypoint, 1368bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski spv::StorageClass sinterface, bool is_array_of_verts) { 13695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_map<unsigned, unsigned> var_locations; 13705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_map<unsigned, unsigned> var_builtins; 13715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_map<unsigned, unsigned> var_components; 13725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_map<unsigned, unsigned> blocks; 1373b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes std::unordered_map<unsigned, unsigned> var_patch; 1374b0436668e6594b8528e96de7bed208399fb2431dChris Forbes std::unordered_map<unsigned, unsigned> var_relaxed_precision; 13755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 13765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto insn : *src) { 137725002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // We consider two interface models: SSO rendezvous-by-location, and builtins. Complain about anything that 137825002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // fits neither model. 13795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.opcode() == spv::OpDecorate) { 13805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.word(2) == spv::DecorationLocation) { 13815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis var_locations[insn.word(1)] = insn.word(3); 13825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 13845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.word(2) == spv::DecorationBuiltIn) { 13855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis var_builtins[insn.word(1)] = insn.word(3); 13865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 13885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.word(2) == spv::DecorationComponent) { 13895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis var_components[insn.word(1)] = insn.word(3); 13905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 13925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.word(2) == spv::DecorationBlock) { 13935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis blocks[insn.word(1)] = 1; 13945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 1395b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes 1396b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes if (insn.word(2) == spv::DecorationPatch) { 1397b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes var_patch[insn.word(1)] = 1; 1398b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes } 1399b0436668e6594b8528e96de7bed208399fb2431dChris Forbes 1400b0436668e6594b8528e96de7bed208399fb2431dChris Forbes if (insn.word(2) == spv::DecorationRelaxedPrecision) { 1401b0436668e6594b8528e96de7bed208399fb2431dChris Forbes var_relaxed_precision[insn.word(1)] = 1; 1402b0436668e6594b8528e96de7bed208399fb2431dChris Forbes } 14035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 14045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 14055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 140625002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // TODO: handle grouped decorations 140725002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // TODO: handle index=1 dual source outputs from FS -- two vars will have the same location, and we DON'T want to clobber. 14085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 140925002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Find the end of the entrypoint's name string. additional zero bytes follow the actual null terminator, to fill out the 141025002b75574f762c62b1a00a595bab04ebb25452Mark 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. 1411c15b801a6e1a5dd5eed09e689aecdde7c4a90a5bMichael Mc Donnell uint32_t word = 3; 14125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis while (entrypoint.word(word) & 0xff000000u) { 14135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis ++word; 14145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 14155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis ++word; 14165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 14173a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes std::map<location_t, interface_var> out; 14183a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes 14195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (; word < entrypoint.len(); word++) { 14205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto insn = src->get_def(entrypoint.word(word)); 14215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(insn != src->end()); 14225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(insn.opcode() == spv::OpVariable); 14235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 14241d5109d5e0dcc530b27e632e73e1be5e12a28dcdJamie Madill if (insn.word(3) == static_cast<uint32_t>(sinterface)) { 14255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned id = insn.word(2); 14265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned type = insn.word(1); 14275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 14285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis int location = value_or_default(var_locations, id, -1); 14295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis int builtin = value_or_default(var_builtins, id, -1); 1430cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski unsigned component = value_or_default(var_components, id, 0); // Unspecified is OK, is 0 1431b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes bool is_patch = var_patch.find(id) != var_patch.end(); 1432b0436668e6594b8528e96de7bed208399fb2431dChris Forbes bool is_relaxed_precision = var_relaxed_precision.find(id) != var_relaxed_precision.end(); 14335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 143425002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // All variables and interface block members in the Input or Output storage classes must be decorated with either 143525002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // a builtin or an explicit location. 143625002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // 143725002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // TODO: integrate the interface block support here. For now, don't complain -- a valid SPIRV module will only hit 143825002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // this path for the interface block case, as the individual members of the type are decorated, rather than 143925002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // variable declarations. 14405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 14415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (location != -1) { 144225002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // A user-defined interface variable, with a location. Where a variable occupied multiple locations, emit 144325002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // one result for each. 14447c755c8aca6857046df9516d8336416165969cb9Chris Forbes unsigned num_locations = get_locations_consumed_by_type(src, type, is_array_of_verts && !is_patch); 14455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (unsigned int offset = 0; offset < num_locations; offset++) { 1446b0436668e6594b8528e96de7bed208399fb2431dChris Forbes interface_var v = {}; 14475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis v.id = id; 14485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis v.type_id = type; 14495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis v.offset = offset; 1450b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes v.is_patch = is_patch; 1451b0436668e6594b8528e96de7bed208399fb2431dChris Forbes v.is_relaxed_precision = is_relaxed_precision; 14525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis out[std::make_pair(location + offset, component)] = v; 14535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 14545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (builtin == -1) { 145525002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // An interface block instance 14563a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes collect_interface_block_members(src, &out, blocks, is_array_of_verts, id, type, is_patch); 14575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 14585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 14595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 14603a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes 14613a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes return out; 14625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 14635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1464cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskistatic std::vector<std::pair<uint32_t, interface_var>> collect_interface_by_input_attachment_index( 1465cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski debug_report_data *report_data, shader_module const *src, std::unordered_set<uint32_t> const &accessible_ids) { 14663a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes std::vector<std::pair<uint32_t, interface_var>> out; 1467745d49409296f060402b57950384caadb636a2b2Chris Forbes 1468745d49409296f060402b57950384caadb636a2b2Chris Forbes for (auto insn : *src) { 1469745d49409296f060402b57950384caadb636a2b2Chris Forbes if (insn.opcode() == spv::OpDecorate) { 1470745d49409296f060402b57950384caadb636a2b2Chris Forbes if (insn.word(2) == spv::DecorationInputAttachmentIndex) { 1471745d49409296f060402b57950384caadb636a2b2Chris Forbes auto attachment_index = insn.word(3); 1472745d49409296f060402b57950384caadb636a2b2Chris Forbes auto id = insn.word(1); 1473745d49409296f060402b57950384caadb636a2b2Chris Forbes 1474745d49409296f060402b57950384caadb636a2b2Chris Forbes if (accessible_ids.count(id)) { 1475745d49409296f060402b57950384caadb636a2b2Chris Forbes auto def = src->get_def(id); 1476745d49409296f060402b57950384caadb636a2b2Chris Forbes assert(def != src->end()); 1477745d49409296f060402b57950384caadb636a2b2Chris Forbes 1478745d49409296f060402b57950384caadb636a2b2Chris Forbes if (def.opcode() == spv::OpVariable && insn.word(3) == spv::StorageClassUniformConstant) { 1479e0cc9b3441a24e4fbd2b4e0a9d163dab2140264aChris Forbes auto num_locations = get_locations_consumed_by_type(src, def.word(1), false); 1480e0cc9b3441a24e4fbd2b4e0a9d163dab2140264aChris Forbes for (unsigned int offset = 0; offset < num_locations; offset++) { 1481b0436668e6594b8528e96de7bed208399fb2431dChris Forbes interface_var v = {}; 1482e0cc9b3441a24e4fbd2b4e0a9d163dab2140264aChris Forbes v.id = id; 1483e0cc9b3441a24e4fbd2b4e0a9d163dab2140264aChris Forbes v.type_id = def.word(1); 1484e0cc9b3441a24e4fbd2b4e0a9d163dab2140264aChris Forbes v.offset = offset; 1485e0cc9b3441a24e4fbd2b4e0a9d163dab2140264aChris Forbes out.emplace_back(attachment_index + offset, v); 1486e0cc9b3441a24e4fbd2b4e0a9d163dab2140264aChris Forbes } 1487745d49409296f060402b57950384caadb636a2b2Chris Forbes } 1488745d49409296f060402b57950384caadb636a2b2Chris Forbes } 1489745d49409296f060402b57950384caadb636a2b2Chris Forbes } 1490745d49409296f060402b57950384caadb636a2b2Chris Forbes } 1491745d49409296f060402b57950384caadb636a2b2Chris Forbes } 14923a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes 14933a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes return out; 1494745d49409296f060402b57950384caadb636a2b2Chris Forbes} 1495745d49409296f060402b57950384caadb636a2b2Chris Forbes 1496cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskistatic std::vector<std::pair<descriptor_slot_t, interface_var>> collect_interface_by_descriptor_slot( 1497cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski debug_report_data *report_data, shader_module const *src, std::unordered_set<uint32_t> const &accessible_ids) { 14985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_map<unsigned, unsigned> var_sets; 14995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_map<unsigned, unsigned> var_bindings; 15005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 15015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto insn : *src) { 150225002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // All variables in the Uniform or UniformConstant storage classes are required to be decorated with both 150325002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // DecorationDescriptorSet and DecorationBinding. 15045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.opcode() == spv::OpDecorate) { 15055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.word(2) == spv::DecorationDescriptorSet) { 15065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis var_sets[insn.word(1)] = insn.word(3); 15075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 15085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 15095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.word(2) == spv::DecorationBinding) { 15105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis var_bindings[insn.word(1)] = insn.word(3); 15115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 15125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 15135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 15145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 15153a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes std::vector<std::pair<descriptor_slot_t, interface_var>> out; 15163a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes 15175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto id : accessible_ids) { 15185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto insn = src->get_def(id); 15195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(insn != src->end()); 15205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 15215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.opcode() == spv::OpVariable && 15225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (insn.word(3) == spv::StorageClassUniform || insn.word(3) == spv::StorageClassUniformConstant)) { 15235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned set = value_or_default(var_sets, insn.word(2), 0); 15245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned binding = value_or_default(var_bindings, insn.word(2), 0); 15255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1526b0436668e6594b8528e96de7bed208399fb2431dChris Forbes interface_var v = {}; 15275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis v.id = insn.word(2); 15285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis v.type_id = insn.word(1); 1529cefd4dd8e03c5dae11a05d04a03cb856190358e0Chris Forbes out.emplace_back(std::make_pair(set, binding), v); 15305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 15315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 15323a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes 15333a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes return out; 15345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 15355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1536edef66e03ed509994449d598f4fadea1a487d41bChris Forbesstatic bool validate_interface_between_stages(debug_report_data *report_data, shader_module const *producer, 1537031261d21af8907953dd763398ce9a23e65b8749Chris Forbes spirv_inst_iter producer_entrypoint, shader_stage_attributes const *producer_stage, 15385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis shader_module const *consumer, spirv_inst_iter consumer_entrypoint, 1539031261d21af8907953dd763398ce9a23e65b8749Chris Forbes shader_stage_attributes const *consumer_stage) { 15405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool pass = true; 15415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1542bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto outputs = 1543bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski collect_interface_by_location(producer, producer_entrypoint, spv::StorageClassOutput, producer_stage->arrayed_output); 1544bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto inputs = 1545bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski collect_interface_by_location(consumer, consumer_entrypoint, spv::StorageClassInput, consumer_stage->arrayed_input); 15465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 15475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto a_it = outputs.begin(); 15485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto b_it = inputs.begin(); 15495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 155025002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Maps sorted by key (location); walk them together to find mismatches 15515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis while ((outputs.size() > 0 && a_it != outputs.end()) || (inputs.size() && b_it != inputs.end())) { 15525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool a_at_end = outputs.size() == 0 || a_it == outputs.end(); 15535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool b_at_end = inputs.size() == 0 || b_it == inputs.end(); 15545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto a_first = a_at_end ? std::make_pair(0u, 0u) : a_it->first; 15555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto b_first = b_at_end ? std::make_pair(0u, 0u) : b_it->first; 15565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 15575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (b_at_end || ((!a_at_end) && (a_first < b_first))) { 1558bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 1559bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SHADER_CHECKER_OUTPUT_NOT_CONSUMED, "SC", "%s writes to output location %u.%u which is not consumed by %s", 1560bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski producer_stage->name, a_first.first, a_first.second, consumer_stage->name)) { 15615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pass = false; 15625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 15635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis a_it++; 15645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (a_at_end || a_first > b_first) { 1565bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 1566bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SHADER_CHECKER_INPUT_NOT_PRODUCED, "SC", "%s consumes input location %u.%u which is not written by %s", 1567bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski consumer_stage->name, b_first.first, b_first.second, producer_stage->name)) { 15685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pass = false; 15695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 15705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis b_it++; 15715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 1572fff9393206f66a154438e16fa0562c989f425498Chris Forbes // subtleties of arrayed interfaces: 1573fff9393206f66a154438e16fa0562c989f425498Chris Forbes // - if is_patch, then the member is not arrayed, even though the interface may be. 1574fff9393206f66a154438e16fa0562c989f425498Chris Forbes // - if is_block_member, then the extra array level of an arrayed interface is not 1575fff9393206f66a154438e16fa0562c989f425498Chris Forbes // expressed in the member type -- it's expressed in the block type. 15760f44c68c2575ba2fc83d8c8f2f5ea09548f40686Chris Forbes if (!types_match(producer, consumer, a_it->second.type_id, b_it->second.type_id, 1577fff9393206f66a154438e16fa0562c989f425498Chris Forbes producer_stage->arrayed_output && !a_it->second.is_patch && !a_it->second.is_block_member, 1578bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski consumer_stage->arrayed_input && !b_it->second.is_patch && !b_it->second.is_block_member, true)) { 1579bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 1580bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SHADER_CHECKER_INTERFACE_TYPE_MISMATCH, "SC", "Type mismatch on location %u.%u: '%s' vs '%s'", 1581bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski a_first.first, a_first.second, describe_type(producer, a_it->second.type_id).c_str(), 15829ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes describe_type(consumer, b_it->second.type_id).c_str())) { 15835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pass = false; 15845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 15855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 15860f44c68c2575ba2fc83d8c8f2f5ea09548f40686Chris Forbes if (a_it->second.is_patch != b_it->second.is_patch) { 1587bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 0, __LINE__, 1588bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SHADER_CHECKER_INTERFACE_TYPE_MISMATCH, "SC", 1589f706c50be3a9d4d1e131c2f43ee2fb443f028d30Chris Forbes "Decoration mismatch on location %u.%u: is per-%s in %s stage but " 1590bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "per-%s in %s stage", 1591bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski a_first.first, a_first.second, a_it->second.is_patch ? "patch" : "vertex", producer_stage->name, 15920f44c68c2575ba2fc83d8c8f2f5ea09548f40686Chris Forbes b_it->second.is_patch ? "patch" : "vertex", consumer_stage->name)) { 15930f44c68c2575ba2fc83d8c8f2f5ea09548f40686Chris Forbes pass = false; 15940f44c68c2575ba2fc83d8c8f2f5ea09548f40686Chris Forbes } 15950f44c68c2575ba2fc83d8c8f2f5ea09548f40686Chris Forbes } 159617c6bacf91ac671cb33212071b87b8ea782812f5Chris Forbes if (a_it->second.is_relaxed_precision != b_it->second.is_relaxed_precision) { 1597bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 0, __LINE__, 1598bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SHADER_CHECKER_INTERFACE_TYPE_MISMATCH, "SC", 1599bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "Decoration mismatch on location %u.%u: %s and %s stages differ in precision", a_first.first, 1600bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski a_first.second, producer_stage->name, consumer_stage->name)) { 160117c6bacf91ac671cb33212071b87b8ea782812f5Chris Forbes pass = false; 160217c6bacf91ac671cb33212071b87b8ea782812f5Chris Forbes } 160317c6bacf91ac671cb33212071b87b8ea782812f5Chris Forbes } 16045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis a_it++; 16055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis b_it++; 16065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 16075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 16085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 16095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return pass; 16105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 16115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 16125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisenum FORMAT_TYPE { 16135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis FORMAT_TYPE_UNDEFINED, 1614cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski FORMAT_TYPE_FLOAT, // UNORM, SNORM, FLOAT, USCALED, SSCALED, SRGB -- anything we consider float in the shader 16155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis FORMAT_TYPE_SINT, 16165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis FORMAT_TYPE_UINT, 16175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}; 16185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 16195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic unsigned get_format_type(VkFormat fmt) { 16205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis switch (fmt) { 1621cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_UNDEFINED: 1622cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return FORMAT_TYPE_UNDEFINED; 1623cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R8_SINT: 1624cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R8G8_SINT: 1625cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R8G8B8_SINT: 1626cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R8G8B8A8_SINT: 1627cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R16_SINT: 1628cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R16G16_SINT: 1629cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R16G16B16_SINT: 1630cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R16G16B16A16_SINT: 1631cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R32_SINT: 1632cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R32G32_SINT: 1633cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R32G32B32_SINT: 1634cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R32G32B32A32_SINT: 1635cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64_SINT: 1636cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64G64_SINT: 1637cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64G64B64_SINT: 1638cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64G64B64A64_SINT: 1639cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_B8G8R8_SINT: 1640cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_B8G8R8A8_SINT: 1641cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_A8B8G8R8_SINT_PACK32: 1642cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_A2B10G10R10_SINT_PACK32: 1643cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_A2R10G10B10_SINT_PACK32: 1644cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return FORMAT_TYPE_SINT; 1645cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R8_UINT: 1646cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R8G8_UINT: 1647cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R8G8B8_UINT: 1648cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R8G8B8A8_UINT: 1649cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R16_UINT: 1650cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R16G16_UINT: 1651cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R16G16B16_UINT: 1652cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R16G16B16A16_UINT: 1653cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R32_UINT: 1654cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R32G32_UINT: 1655cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R32G32B32_UINT: 1656cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R32G32B32A32_UINT: 1657cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64_UINT: 1658cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64G64_UINT: 1659cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64G64B64_UINT: 1660cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64G64B64A64_UINT: 1661cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_B8G8R8_UINT: 1662cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_B8G8R8A8_UINT: 1663cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_A8B8G8R8_UINT_PACK32: 1664cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_A2B10G10R10_UINT_PACK32: 1665cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_A2R10G10B10_UINT_PACK32: 1666cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return FORMAT_TYPE_UINT; 1667cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 1668cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return FORMAT_TYPE_FLOAT; 16695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 16705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 16715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 167225002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// characterizes a SPIR-V type appearing in an interface to a FF stage, for comparison to a VkFormat's characterization above. 16735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic unsigned get_fundamental_type(shader_module const *src, unsigned type) { 16745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto insn = src->get_def(type); 16755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(insn != src->end()); 16765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 16775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis switch (insn.opcode()) { 1678cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeInt: 1679cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return insn.word(3) ? FORMAT_TYPE_SINT : FORMAT_TYPE_UINT; 1680cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeFloat: 1681cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return FORMAT_TYPE_FLOAT; 1682cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeVector: 1683cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return get_fundamental_type(src, insn.word(2)); 1684cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeMatrix: 1685cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return get_fundamental_type(src, insn.word(2)); 1686cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeArray: 1687cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return get_fundamental_type(src, insn.word(2)); 1688cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypePointer: 1689cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return get_fundamental_type(src, insn.word(3)); 1690cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeImage: 1691cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return get_fundamental_type(src, insn.word(2)); 1692cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski 1693cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 1694cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return FORMAT_TYPE_UNDEFINED; 16955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 16965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 16975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 16985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic uint32_t get_shader_stage_id(VkShaderStageFlagBits stage) { 16995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t bit_pos = u_ffs(stage); 17005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return bit_pos - 1; 17015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 17025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1703edef66e03ed509994449d598f4fadea1a487d41bChris Forbesstatic bool validate_vi_consistency(debug_report_data *report_data, VkPipelineVertexInputStateCreateInfo const *vi) { 170425002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Walk the binding descriptions, which describe the step rate and stride of each vertex buffer. Each binding should 170525002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // be specified only once. 17065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_map<uint32_t, VkVertexInputBindingDescription const *> bindings; 17075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool pass = true; 17085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 17095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (unsigned i = 0; i < vi->vertexBindingDescriptionCount; i++) { 17105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto desc = &vi->pVertexBindingDescriptions[i]; 17115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto &binding = bindings[desc->binding]; 17125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (binding) { 17134f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes // TODO: VALIDATION_ERROR_02105 perhaps? 1714bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 1715bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SHADER_CHECKER_INCONSISTENT_VI, "SC", "Duplicate vertex input binding descriptions for binding %d", 1716bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski desc->binding)) { 17175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pass = false; 17185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 17205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis binding = desc; 17215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 17245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return pass; 17255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 17265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1727edef66e03ed509994449d598f4fadea1a487d41bChris Forbesstatic bool validate_vi_against_vs_inputs(debug_report_data *report_data, VkPipelineVertexInputStateCreateInfo const *vi, 17285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis shader_module const *vs, spirv_inst_iter entrypoint) { 17295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool pass = true; 17305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 17313a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes auto inputs = collect_interface_by_location(vs, entrypoint, spv::StorageClassInput, false); 17325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 173325002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Build index by location 17345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::map<uint32_t, VkVertexInputAttributeDescription const *> attribs; 17355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (vi) { 1736c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes for (unsigned i = 0; i < vi->vertexAttributeDescriptionCount; i++) { 1737c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes auto num_locations = get_locations_consumed_by_format(vi->pVertexAttributeDescriptions[i].format); 1738c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes for (auto j = 0u; j < num_locations; j++) { 1739c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes attribs[vi->pVertexAttributeDescriptions[i].location + j] = &vi->pVertexAttributeDescriptions[i]; 1740c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes } 1741c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes } 17425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 17445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto it_a = attribs.begin(); 17455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto it_b = inputs.begin(); 17461730e0dd28b3abc660b4e4704cf6d414f7fd4ad6Chris Forbes bool used = false; 17475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 17485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis while ((attribs.size() > 0 && it_a != attribs.end()) || (inputs.size() > 0 && it_b != inputs.end())) { 17495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool a_at_end = attribs.size() == 0 || it_a == attribs.end(); 17505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool b_at_end = inputs.size() == 0 || it_b == inputs.end(); 17515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto a_first = a_at_end ? 0 : it_a->first; 17525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto b_first = b_at_end ? 0 : it_b->first.first; 17535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!a_at_end && (b_at_end || a_first < b_first)) { 17541730e0dd28b3abc660b4e4704cf6d414f7fd4ad6Chris Forbes if (!used && log_msg(report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, 1755bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski __LINE__, SHADER_CHECKER_OUTPUT_NOT_CONSUMED, "SC", 1756bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "Vertex attribute at location %d not consumed by vertex shader", a_first)) { 17575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pass = false; 17585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17591730e0dd28b3abc660b4e4704cf6d414f7fd4ad6Chris Forbes used = false; 17605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis it_a++; 17615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (!b_at_end && (a_at_end || b_first < a_first)) { 1762bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 0, __LINE__, 1763bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SHADER_CHECKER_INPUT_NOT_PRODUCED, "SC", "Vertex shader consumes input at location %d but not provided", 17645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis b_first)) { 17655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pass = false; 17665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis it_b++; 17685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 17695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned attrib_type = get_format_type(it_a->second->format); 17705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned input_type = get_fundamental_type(vs, it_b->second.type_id); 17715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 177225002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Type checking 17735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (attrib_type != FORMAT_TYPE_UNDEFINED && input_type != FORMAT_TYPE_UNDEFINED && attrib_type != input_type) { 1774bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 1775bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SHADER_CHECKER_INTERFACE_TYPE_MISMATCH, "SC", 17764b5890faffa54a735782a6b0a628a991ddc86944Mike Weiblen "Attribute type of `%s` at location %d does not match vertex shader input type of `%s`", 1777bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski string_VkFormat(it_a->second->format), a_first, describe_type(vs, it_b->second.type_id).c_str())) { 17785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pass = false; 17795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 178225002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // OK! 17831730e0dd28b3abc660b4e4704cf6d414f7fd4ad6Chris Forbes used = true; 17845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis it_b++; 17855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 17885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return pass; 17895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 17905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1791edef66e03ed509994449d598f4fadea1a487d41bChris Forbesstatic bool validate_fs_outputs_against_render_pass(debug_report_data *report_data, shader_module const *fs, 17928da1edac0fbed13831b2f458f27c51e64d6210ffTobin Ehlis spirv_inst_iter entrypoint, VkRenderPassCreateInfo const *rpci, 17938da1edac0fbed13831b2f458f27c51e64d6210ffTobin Ehlis uint32_t subpass_index) { 1794025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes std::map<uint32_t, VkFormat> color_attachments; 17958da1edac0fbed13831b2f458f27c51e64d6210ffTobin Ehlis auto subpass = rpci->pSubpasses[subpass_index]; 17968da1edac0fbed13831b2f458f27c51e64d6210ffTobin Ehlis for (auto i = 0u; i < subpass.colorAttachmentCount; ++i) { 1797d9da90d92748c37962766868f8b0354637672c2aTobin Ehlis uint32_t attachment = subpass.pColorAttachments[i].attachment; 1798cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (attachment == VK_ATTACHMENT_UNUSED) continue; 1799d9da90d92748c37962766868f8b0354637672c2aTobin Ehlis if (rpci->pAttachments[attachment].format != VK_FORMAT_UNDEFINED) { 1800d9da90d92748c37962766868f8b0354637672c2aTobin Ehlis color_attachments[i] = rpci->pAttachments[attachment].format; 1801025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes } 1802025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes } 1803025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes 18045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool pass = true; 18055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 180625002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // TODO: dual source blend index (spv::DecIndex, zero if not provided) 18075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 18083a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes auto outputs = collect_interface_by_location(fs, entrypoint, spv::StorageClassOutput, false); 18095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1810025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes auto it_a = outputs.begin(); 1811025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes auto it_b = color_attachments.begin(); 18125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 181325002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Walk attachment list and outputs together 1814025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes 1815025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes while ((outputs.size() > 0 && it_a != outputs.end()) || (color_attachments.size() > 0 && it_b != color_attachments.end())) { 1816025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes bool a_at_end = outputs.size() == 0 || it_a == outputs.end(); 1817025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes bool b_at_end = color_attachments.size() == 0 || it_b == color_attachments.end(); 18185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1819025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes if (!a_at_end && (b_at_end || it_a->first.first < it_b->first)) { 1820bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 1821bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SHADER_CHECKER_OUTPUT_NOT_CONSUMED, "SC", 1822d79335137b414d5f89284a9ab3e014beb4ada3ebMike Weiblen "fragment shader writes to output location %d with no matching attachment", it_a->first.first)) { 18235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pass = false; 18245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 1825025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes it_a++; 1826025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes } else if (!b_at_end && (a_at_end || it_a->first.first > it_b->first)) { 1827bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 1828bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SHADER_CHECKER_INPUT_NOT_PRODUCED, "SC", "Attachment %d not written by fragment shader", it_b->first)) { 18295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pass = false; 18305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 1831025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes it_b++; 18325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 1833025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes unsigned output_type = get_fundamental_type(fs, it_a->second.type_id); 1834025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes unsigned att_type = get_format_type(it_b->second); 18355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 183625002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Type checking 18375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (att_type != FORMAT_TYPE_UNDEFINED && output_type != FORMAT_TYPE_UNDEFINED && att_type != output_type) { 1838bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 1839bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SHADER_CHECKER_INTERFACE_TYPE_MISMATCH, "SC", 1840d79335137b414d5f89284a9ab3e014beb4ada3ebMike Weiblen "Attachment %d of type `%s` does not match fragment shader output type of `%s`", it_b->first, 1841bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski string_VkFormat(it_b->second), describe_type(fs, it_a->second.type_id).c_str())) { 18425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pass = false; 18435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 18445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 18455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 184625002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // OK! 1847025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes it_a++; 1848025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes it_b++; 18495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 18505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 18515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 18525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return pass; 18535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 18545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 185525002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// For some analyses, we need to know about all ids referenced by the static call tree of a particular entrypoint. This is 185625002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// important for identifying the set of shader resources actually used by an entrypoint, for example. 185725002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// Note: we only explore parts of the image which might actually contain ids we care about for the above analyses. 185825002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// - NOT the shader input/output interfaces. 185925002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// 186025002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// TODO: The set of interesting opcodes here was determined by eyeballing the SPIRV spec. It might be worth 186125002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// converting parts of this to be generated from the machine-readable spec instead. 18623a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbesstatic std::unordered_set<uint32_t> mark_accessible_ids(shader_module const *src, spirv_inst_iter entrypoint) { 18633a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes std::unordered_set<uint32_t> ids; 18645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_set<uint32_t> worklist; 18655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis worklist.insert(entrypoint.word(2)); 18665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 18675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis while (!worklist.empty()) { 18685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto id_iter = worklist.begin(); 18695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto id = *id_iter; 18705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis worklist.erase(id_iter); 18715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 18725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto insn = src->get_def(id); 18735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn == src->end()) { 187425002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // ID is something we didn't collect in build_def_index. that's OK -- we'll stumble across all kinds of things here 187525002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // that we may not care about. 18765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis continue; 18775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 18785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 187925002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Try to add to the output set 18805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!ids.insert(id).second) { 1881cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski continue; // If we already saw this id, we don't want to walk it again. 18825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 18835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 18845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis switch (insn.opcode()) { 1885cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpFunction: 1886cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Scan whole body of the function, enlisting anything interesting 1887cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski while (++insn, insn.opcode() != spv::OpFunctionEnd) { 1888cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski switch (insn.opcode()) { 1889cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpLoad: 1890cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicLoad: 1891cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicExchange: 1892cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicCompareExchange: 1893cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicCompareExchangeWeak: 1894cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicIIncrement: 1895cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicIDecrement: 1896cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicIAdd: 1897cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicISub: 1898cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicSMin: 1899cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicUMin: 1900cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicSMax: 1901cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicUMax: 1902cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicAnd: 1903cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicOr: 1904cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicXor: 1905cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski worklist.insert(insn.word(3)); // ptr 1906cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1907cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpStore: 1908cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicStore: 1909cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski worklist.insert(insn.word(1)); // ptr 1910cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1911cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAccessChain: 1912cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpInBoundsAccessChain: 1913cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski worklist.insert(insn.word(3)); // base ptr 1914cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1915cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpSampledImage: 1916cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSampleImplicitLod: 1917cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSampleExplicitLod: 1918cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSampleDrefImplicitLod: 1919cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSampleDrefExplicitLod: 1920cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSampleProjImplicitLod: 1921cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSampleProjExplicitLod: 1922cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSampleProjDrefImplicitLod: 1923cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSampleProjDrefExplicitLod: 1924cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageFetch: 1925cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageGather: 1926cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageDrefGather: 1927cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageRead: 1928cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImage: 1929cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageQueryFormat: 1930cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageQueryOrder: 1931cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageQuerySizeLod: 1932cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageQuerySize: 1933cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageQueryLod: 1934cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageQueryLevels: 1935cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageQuerySamples: 1936cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSparseSampleImplicitLod: 1937cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSparseSampleExplicitLod: 1938cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSparseSampleDrefImplicitLod: 1939cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSparseSampleDrefExplicitLod: 1940cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSparseSampleProjImplicitLod: 1941cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSparseSampleProjExplicitLod: 1942cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSparseSampleProjDrefImplicitLod: 1943cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSparseSampleProjDrefExplicitLod: 1944cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSparseFetch: 1945cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSparseGather: 1946cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSparseDrefGather: 1947cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageTexelPointer: 1948cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski worklist.insert(insn.word(3)); // Image or sampled image 1949cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1950cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageWrite: 1951cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski worklist.insert(insn.word(1)); // Image -- different operand order to above 1952cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1953cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpFunctionCall: 1954cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski for (uint32_t i = 3; i < insn.len(); i++) { 1955cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski worklist.insert(insn.word(i)); // fn itself, and all args 1956cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 1957cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 19585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1959cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpExtInst: 1960cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski for (uint32_t i = 5; i < insn.len(); i++) { 1961cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski worklist.insert(insn.word(i)); // Operands to ext inst 1962cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 1963cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 19645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 19655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 1966cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 19675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 19685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 19693a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes 19703a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes return ids; 19715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 19725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1973edef66e03ed509994449d598f4fadea1a487d41bChris Forbesstatic bool validate_push_constant_block_against_pipeline(debug_report_data *report_data, 1974416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis std::vector<VkPushConstantRange> const *push_constant_ranges, 19755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis shader_module const *src, spirv_inst_iter type, 19765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkShaderStageFlagBits stage) { 19775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool pass = true; 19785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 197925002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Strip off ptrs etc 19805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis type = get_struct_type(src, type, false); 19815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(type != src->end()); 19825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 198325002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Validate directly off the offsets. this isn't quite correct for arrays and matrices, but is a good first step. 198425002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // TODO: arrays, matrices, weird sizes 19855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto insn : *src) { 19865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.opcode() == spv::OpMemberDecorate && insn.word(1) == type.word(1)) { 19875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.word(3) == spv::DecorationOffset) { 19885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned offset = insn.word(4); 1989cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski auto size = 4; // Bytes; TODO: calculate this based on the type 19905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 19915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool found_range = false; 1992416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis for (auto const &range : *push_constant_ranges) { 19935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (range.offset <= offset && range.offset + range.size >= offset + size) { 19945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis found_range = true; 19955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 19965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if ((range.stageFlags & stage) == 0) { 1997bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 1998bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SHADER_CHECKER_PUSH_CONSTANT_NOT_ACCESSIBLE_FROM_STAGE, "SC", 19995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis "Push constant range covering variable starting at " 20005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis "offset %u not accessible from stage %s", 20015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis offset, string_VkShaderStageFlagBits(stage))) { 20025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pass = false; 20035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 20045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 20055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 20065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis break; 20075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 20085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 20095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 20105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!found_range) { 2011bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 2012bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SHADER_CHECKER_PUSH_CONSTANT_OUT_OF_RANGE, "SC", 20135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis "Push constant range covering variable starting at " 20145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis "offset %u not declared in layout", 20155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis offset)) { 20165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pass = false; 20175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 20185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 20195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 20205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 20215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 20225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 20235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return pass; 20245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 20255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2026edef66e03ed509994449d598f4fadea1a487d41bChris Forbesstatic bool validate_push_constant_usage(debug_report_data *report_data, 2027416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis std::vector<VkPushConstantRange> const *push_constant_ranges, shader_module const *src, 20285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_set<uint32_t> accessible_ids, VkShaderStageFlagBits stage) { 20295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool pass = true; 20305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 20315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto id : accessible_ids) { 20325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto def_insn = src->get_def(id); 20335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (def_insn.opcode() == spv::OpVariable && def_insn.word(3) == spv::StorageClassPushConstant) { 2034416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis pass &= validate_push_constant_block_against_pipeline(report_data, push_constant_ranges, src, 2035416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis src->get_def(def_insn.word(1)), stage); 20365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 20375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 20385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 20395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return pass; 20405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 20415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2042fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis// For given pipelineLayout verify that the set_layout_node at slot.first 2043fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis// has the requested binding at slot.second and return ptr to that binding 2044bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic VkDescriptorSetLayoutBinding const *get_descriptor_binding(PIPELINE_LAYOUT_NODE const *pipelineLayout, 2045bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski descriptor_slot_t slot) { 2046cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!pipelineLayout) return nullptr; 20475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2048cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (slot.first >= pipelineLayout->set_layouts.size()) return nullptr; 20495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2050416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis return pipelineLayout->set_layouts[slot.first]->GetDescriptorSetLayoutBindingPtrFromBinding(slot.second); 20515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 20525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 20535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Check object status for selected flag state 205451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool validate_status(layer_data *dev_data, GLOBAL_CB_NODE *pNode, CBStatusFlags status_mask, VkFlags msg_flags, 20554f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes const char *fail_msg, UNIQUE_VALIDATION_ERROR_CODE const msg_code) { 20563d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis if (!(pNode->status & status_mask)) { 20574f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes char const *const message = validation_error_map[msg_code]; 205851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis return log_msg(dev_data->report_data, msg_flags, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 20594f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes reinterpret_cast<const uint64_t &>(pNode->commandBuffer), __LINE__, msg_code, "DS", 20604f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "command buffer object 0x%p: %s. %s.", pNode->commandBuffer, fail_msg, message); 20615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 2062e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves return false; 20635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 20645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 20655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Retrieve pipeline node ptr for given pipeline object 206651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic PIPELINE_STATE *getPipelineState(layer_data const *dev_data, VkPipeline pipeline) { 206751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis auto it = dev_data->pipelineMap.find(pipeline); 206851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (it == dev_data->pipelineMap.end()) { 2069ea8349eeee76ae2859c10870fd8bd9e60309eb28Chris Forbes return nullptr; 20705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 2071ea8349eeee76ae2859c10870fd8bd9e60309eb28Chris Forbes return it->second; 20725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 20735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 20749a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisRENDER_PASS_STATE *GetRenderPassState(layer_data const *dev_data, VkRenderPass renderpass) { 207551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis auto it = dev_data->renderPassMap.find(renderpass); 207651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (it == dev_data->renderPassMap.end()) { 207716387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes return nullptr; 207816387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes } 2079fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes return it->second.get(); 208016387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes} 208116387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes 20829a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisFRAMEBUFFER_STATE *GetFramebufferState(const layer_data *dev_data, VkFramebuffer framebuffer) { 208351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis auto it = dev_data->frameBufferMap.find(framebuffer); 208451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (it == dev_data->frameBufferMap.end()) { 2085f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes return nullptr; 2086f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes } 208704861caca7eb93a5241b164e8480bb93c826902cTobin Ehlis return it->second.get(); 2088f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes} 2089f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes 20909a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehliscvdescriptorset::DescriptorSetLayout const *GetDescriptorSetLayout(layer_data const *dev_data, VkDescriptorSetLayout dsLayout) { 209151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis auto it = dev_data->descriptorSetLayoutMap.find(dsLayout); 209251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (it == dev_data->descriptorSetLayoutMap.end()) { 209311f1fde2721c198a619e4a22fff60eef9a16fae8Chris Forbes return nullptr; 209411f1fde2721c198a619e4a22fff60eef9a16fae8Chris Forbes } 209511f1fde2721c198a619e4a22fff60eef9a16fae8Chris Forbes return it->second; 209611f1fde2721c198a619e4a22fff60eef9a16fae8Chris Forbes} 209711f1fde2721c198a619e4a22fff60eef9a16fae8Chris Forbes 209851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic PIPELINE_LAYOUT_NODE const *getPipelineLayout(layer_data const *dev_data, VkPipelineLayout pipeLayout) { 209951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis auto it = dev_data->pipelineLayoutMap.find(pipeLayout); 210051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (it == dev_data->pipelineLayoutMap.end()) { 21014a45a42023b281f55953222c1a6c3e80f50e5f2aChris Forbes return nullptr; 21024a45a42023b281f55953222c1a6c3e80f50e5f2aChris Forbes } 21034a45a42023b281f55953222c1a6c3e80f50e5f2aChris Forbes return &it->second; 21044a45a42023b281f55953222c1a6c3e80f50e5f2aChris Forbes} 21054a45a42023b281f55953222c1a6c3e80f50e5f2aChris Forbes 2106e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves// Return true if for a given PSO, the given state enum is dynamic, else return false 21074c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlisstatic bool isDynamic(const PIPELINE_STATE *pPipeline, const VkDynamicState state) { 21085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pPipeline && pPipeline->graphicsPipelineCI.pDynamicState) { 21095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < pPipeline->graphicsPipelineCI.pDynamicState->dynamicStateCount; i++) { 2110cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (state == pPipeline->graphicsPipelineCI.pDynamicState->pDynamicStates[i]) return true; 21115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 21125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 2113e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves return false; 21145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 21155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 21165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Validate state stored as flags at time of draw call 21174f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayesstatic bool validate_draw_state_flags(layer_data *dev_data, GLOBAL_CB_NODE *pCB, const PIPELINE_STATE *pPipe, bool indexed, 21184f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes UNIQUE_VALIDATION_ERROR_CODE const msg_code) { 21199c4006684a13db43f0dbc8d0015a9ef34872ca09Chris Forbes bool result = false; 2120ca546210846c65808717f8875deae39bd227c240Tobin Ehlis if (pPipe->graphicsPipelineCI.pInputAssemblyState && 2121ca546210846c65808717f8875deae39bd227c240Tobin Ehlis ((pPipe->graphicsPipelineCI.pInputAssemblyState->topology == VK_PRIMITIVE_TOPOLOGY_LINE_LIST) || 2122ca546210846c65808717f8875deae39bd227c240Tobin Ehlis (pPipe->graphicsPipelineCI.pInputAssemblyState->topology == VK_PRIMITIVE_TOPOLOGY_LINE_STRIP))) { 21233d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis result |= validate_status(dev_data, pCB, CBSTATUS_LINE_WIDTH_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, 21244f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "Dynamic line width state not set for this command buffer", msg_code); 21253d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 212645824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves if (pPipe->graphicsPipelineCI.pRasterizationState && 212745824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves (pPipe->graphicsPipelineCI.pRasterizationState->depthBiasEnable == VK_TRUE)) { 21283d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis result |= validate_status(dev_data, pCB, CBSTATUS_DEPTH_BIAS_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, 21294f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "Dynamic depth bias state not set for this command buffer", msg_code); 21303d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 21313d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis if (pPipe->blendConstantsEnabled) { 21323d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis result |= validate_status(dev_data, pCB, CBSTATUS_BLEND_CONSTANTS_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, 21334f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "Dynamic blend constants state not set for this command buffer", msg_code); 21343d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 213545824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves if (pPipe->graphicsPipelineCI.pDepthStencilState && 213645824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves (pPipe->graphicsPipelineCI.pDepthStencilState->depthBoundsTestEnable == VK_TRUE)) { 21373d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis result |= validate_status(dev_data, pCB, CBSTATUS_DEPTH_BOUNDS_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, 21384f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "Dynamic depth bounds state not set for this command buffer", msg_code); 21393d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 214045824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves if (pPipe->graphicsPipelineCI.pDepthStencilState && 214145824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves (pPipe->graphicsPipelineCI.pDepthStencilState->stencilTestEnable == VK_TRUE)) { 21423d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis result |= validate_status(dev_data, pCB, CBSTATUS_STENCIL_READ_MASK_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, 21434f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "Dynamic stencil read mask state not set for this command buffer", msg_code); 21443d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis result |= validate_status(dev_data, pCB, CBSTATUS_STENCIL_WRITE_MASK_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, 21454f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "Dynamic stencil write mask state not set for this command buffer", msg_code); 21463d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis result |= validate_status(dev_data, pCB, CBSTATUS_STENCIL_REFERENCE_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, 21474f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "Dynamic stencil reference state not set for this command buffer", msg_code); 21483d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 21491c130ea631a82716dc7334de17767536525f2292Tobin Ehlis if (indexed) { 21503d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis result |= validate_status(dev_data, pCB, CBSTATUS_INDEX_BUFFER_BOUND, VK_DEBUG_REPORT_ERROR_BIT_EXT, 21514f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "Index buffer object not bound to this command buffer when Indexed Draw attempted", msg_code); 21523d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 21534f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes 21545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 21555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 21565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 21575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Verify attachment reference compatibility according to spec 21585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// If one array is larger, treat missing elements of shorter array as VK_ATTACHMENT_UNUSED & other array much match this 21595ca3c071afc98f9144f489b74aa3affaa93633b0Mark Lobodzinski// If both AttachmentReference arrays have requested index, check their corresponding AttachmentDescriptions 21605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// to make sure that format and samples counts match. 21615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// If not, they are not compatible. 21625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic bool attachment_references_compatible(const uint32_t index, const VkAttachmentReference *pPrimary, 21635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const uint32_t primaryCount, const VkAttachmentDescription *pPrimaryAttachments, 21645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkAttachmentReference *pSecondary, const uint32_t secondaryCount, 21655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkAttachmentDescription *pSecondaryAttachments) { 2166e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis // Check potential NULL cases first to avoid nullptr issues later 2167e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis if (pPrimary == nullptr) { 2168e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis if (pSecondary == nullptr) { 2169e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis return true; 2170e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis } 2171e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis return false; 2172e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis } else if (pSecondary == nullptr) { 2173e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis return false; 2174e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis } 2175cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (index >= primaryCount) { // Check secondary as if primary is VK_ATTACHMENT_UNUSED 2176cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (VK_ATTACHMENT_UNUSED == pSecondary[index].attachment) return true; 2177cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else if (index >= secondaryCount) { // Check primary as if secondary is VK_ATTACHMENT_UNUSED 2178cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (VK_ATTACHMENT_UNUSED == pPrimary[index].attachment) return true; 2179cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else { // Format and sample count must match 21805ca3c071afc98f9144f489b74aa3affaa93633b0Mark Lobodzinski if ((pPrimary[index].attachment == VK_ATTACHMENT_UNUSED) && (pSecondary[index].attachment == VK_ATTACHMENT_UNUSED)) { 21815ca3c071afc98f9144f489b74aa3affaa93633b0Mark Lobodzinski return true; 21825ca3c071afc98f9144f489b74aa3affaa93633b0Mark Lobodzinski } else if ((pPrimary[index].attachment == VK_ATTACHMENT_UNUSED) || (pSecondary[index].attachment == VK_ATTACHMENT_UNUSED)) { 21835ca3c071afc98f9144f489b74aa3affaa93633b0Mark Lobodzinski return false; 21845ca3c071afc98f9144f489b74aa3affaa93633b0Mark Lobodzinski } 21855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if ((pPrimaryAttachments[pPrimary[index].attachment].format == 21865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pSecondaryAttachments[pSecondary[index].attachment].format) && 21875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (pPrimaryAttachments[pPrimary[index].attachment].samples == 21885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pSecondaryAttachments[pSecondary[index].attachment].samples)) 21895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return true; 21905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 21915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Format and sample counts didn't match 21925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 21935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 2194a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis// TODO : Scrub verify_renderpass_compatibility() and validateRenderPassCompatibility() and unify them and/or share code 21958da1edac0fbed13831b2f458f27c51e64d6210ffTobin Ehlis// For given primary RenderPass object and secondry RenderPassCreateInfo, verify that they're compatible 219651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool verify_renderpass_compatibility(const layer_data *dev_data, const VkRenderPassCreateInfo *primaryRPCI, 21978da1edac0fbed13831b2f458f27c51e64d6210ffTobin Ehlis const VkRenderPassCreateInfo *secondaryRPCI, string &errorMsg) { 21985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (primaryRPCI->subpassCount != secondaryRPCI->subpassCount) { 2199c07fa78efa7d4edfaa4ffbb0c2046ee8154b27beChris Forbes stringstream errorStr; 22005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis errorStr << "RenderPass for primary cmdBuffer has " << primaryRPCI->subpassCount 22015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis << " subpasses but renderPass for secondary cmdBuffer has " << secondaryRPCI->subpassCount << " subpasses."; 22025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis errorMsg = errorStr.str(); 22035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 22045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 22055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t spIndex = 0; 22065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (spIndex = 0; spIndex < primaryRPCI->subpassCount; ++spIndex) { 22075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // For each subpass, verify that corresponding color, input, resolve & depth/stencil attachment references are compatible 22085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t primaryColorCount = primaryRPCI->pSubpasses[spIndex].colorAttachmentCount; 22095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t secondaryColorCount = secondaryRPCI->pSubpasses[spIndex].colorAttachmentCount; 22105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t colorMax = std::max(primaryColorCount, secondaryColorCount); 22115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t cIdx = 0; cIdx < colorMax; ++cIdx) { 22125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!attachment_references_compatible(cIdx, primaryRPCI->pSubpasses[spIndex].pColorAttachments, primaryColorCount, 22135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis primaryRPCI->pAttachments, secondaryRPCI->pSubpasses[spIndex].pColorAttachments, 22145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis secondaryColorCount, secondaryRPCI->pAttachments)) { 2215c07fa78efa7d4edfaa4ffbb0c2046ee8154b27beChris Forbes stringstream errorStr; 22165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis errorStr << "color attachments at index " << cIdx << " of subpass index " << spIndex << " are not compatible."; 22175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis errorMsg = errorStr.str(); 22185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 22195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (!attachment_references_compatible(cIdx, primaryRPCI->pSubpasses[spIndex].pResolveAttachments, 22205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis primaryColorCount, primaryRPCI->pAttachments, 22215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis secondaryRPCI->pSubpasses[spIndex].pResolveAttachments, 22225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis secondaryColorCount, secondaryRPCI->pAttachments)) { 2223c07fa78efa7d4edfaa4ffbb0c2046ee8154b27beChris Forbes stringstream errorStr; 22245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis errorStr << "resolve attachments at index " << cIdx << " of subpass index " << spIndex << " are not compatible."; 22255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis errorMsg = errorStr.str(); 22265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 22275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 22285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 2229fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes 2230bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (!attachment_references_compatible(0, primaryRPCI->pSubpasses[spIndex].pDepthStencilAttachment, 1, 2231bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski primaryRPCI->pAttachments, secondaryRPCI->pSubpasses[spIndex].pDepthStencilAttachment, 2232fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes 1, secondaryRPCI->pAttachments)) { 2233c07fa78efa7d4edfaa4ffbb0c2046ee8154b27beChris Forbes stringstream errorStr; 2234fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes errorStr << "depth/stencil attachments of subpass index " << spIndex << " are not compatible."; 2235fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes errorMsg = errorStr.str(); 2236fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes return false; 2237fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes } 2238fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes 22395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t primaryInputCount = primaryRPCI->pSubpasses[spIndex].inputAttachmentCount; 22405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t secondaryInputCount = secondaryRPCI->pSubpasses[spIndex].inputAttachmentCount; 22415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t inputMax = std::max(primaryInputCount, secondaryInputCount); 22425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < inputMax; ++i) { 22435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!attachment_references_compatible(i, primaryRPCI->pSubpasses[spIndex].pInputAttachments, primaryColorCount, 22445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis primaryRPCI->pAttachments, secondaryRPCI->pSubpasses[spIndex].pInputAttachments, 22455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis secondaryColorCount, secondaryRPCI->pAttachments)) { 2246c07fa78efa7d4edfaa4ffbb0c2046ee8154b27beChris Forbes stringstream errorStr; 22475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis errorStr << "input attachments at index " << i << " of subpass index " << spIndex << " are not compatible."; 22485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis errorMsg = errorStr.str(); 22495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 22505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 22515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 22525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 22535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return true; 22545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 22555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2256397d27da37095073c8b86f9ff5289d0a39ce486eTobin Ehlis// For given cvdescriptorset::DescriptorSet, verify that its Set is compatible w/ the setLayout corresponding to 2257397d27da37095073c8b86f9ff5289d0a39ce486eTobin Ehlis// pipelineLayout[layoutIndex] 225851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool verify_set_layout_compatibility(layer_data *dev_data, const cvdescriptorset::DescriptorSet *descriptor_set, 225969b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis PIPELINE_LAYOUT_NODE const *pipeline_layout, const uint32_t layoutIndex, 226069b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis string &errorMsg) { 2261416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis auto num_sets = pipeline_layout->set_layouts.size(); 22629b5d124aff50234cb0450e1b805baef577c90d83Tobin Ehlis if (layoutIndex >= num_sets) { 2263c07fa78efa7d4edfaa4ffbb0c2046ee8154b27beChris Forbes stringstream errorStr; 226469b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis errorStr << "VkPipelineLayout (" << pipeline_layout->layout << ") only contains " << num_sets 226569b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis << " setLayouts corresponding to sets 0-" << num_sets - 1 << ", but you're attempting to bind set to index " 226669b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis << layoutIndex; 22675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis errorMsg = errorStr.str(); 22685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 22695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 2270416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis auto layout_node = pipeline_layout->set_layouts[layoutIndex]; 22711c130ea631a82716dc7334de17767536525f2292Tobin Ehlis return descriptor_set->IsCompatible(layout_node, &errorMsg); 22725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 22735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 22745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Validate that data for each specialization entry is fully contained within the buffer. 2275edef66e03ed509994449d598f4fadea1a487d41bChris Forbesstatic bool validate_specialization_offsets(debug_report_data *report_data, VkPipelineShaderStageCreateInfo const *info) { 2276e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool pass = true; 22775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 22785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkSpecializationInfo const *spec = info->pSpecializationInfo; 22795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 22805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (spec) { 22815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto i = 0u; i < spec->mapEntryCount; i++) { 22824f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes // TODO: This is a good place for VALIDATION_ERROR_00589. 22835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (spec->pMapEntries[i].offset + spec->pMapEntries[i].size > spec->dataSize) { 22844f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 0, __LINE__, 22854f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes VALIDATION_ERROR_00590, "SC", 22865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis "Specialization entry %u (for constant id %u) references memory outside provided " 22875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis "specialization data (bytes %u.." PRINTF_SIZE_T_SPECIFIER "; " PRINTF_SIZE_T_SPECIFIER 22884f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes " bytes provided). %s.", 22895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis i, spec->pMapEntries[i].constantID, spec->pMapEntries[i].offset, 22904f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes spec->pMapEntries[i].offset + spec->pMapEntries[i].size - 1, spec->dataSize, 22914f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes validation_error_map[VALIDATION_ERROR_00590])) { 2292e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves pass = false; 22935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 22945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 22955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 22965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 22975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 22985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return pass; 22995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 23005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2301bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic bool descriptor_type_match(shader_module const *module, uint32_t type_id, VkDescriptorType descriptor_type, 2302bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski unsigned &descriptor_count) { 23035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto type = module->get_def(type_id); 23045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 23051b8c581791ac3c05d7829e04a2d8ecb964b8f2a6Chris Forbes descriptor_count = 1; 23061b8c581791ac3c05d7829e04a2d8ecb964b8f2a6Chris Forbes 230725002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Strip off any array or ptrs. Where we remove array levels, adjust the descriptor count for each dimension. 23085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis while (type.opcode() == spv::OpTypeArray || type.opcode() == spv::OpTypePointer) { 23097b892d2fc502b57d26dc9bff61b0f23cccc595fdChris Forbes if (type.opcode() == spv::OpTypeArray) { 23107b892d2fc502b57d26dc9bff61b0f23cccc595fdChris Forbes descriptor_count *= get_constant_value(module, type.word(3)); 23117b892d2fc502b57d26dc9bff61b0f23cccc595fdChris Forbes type = module->get_def(type.word(2)); 2312bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski } else { 23137b892d2fc502b57d26dc9bff61b0f23cccc595fdChris Forbes type = module->get_def(type.word(3)); 23147b892d2fc502b57d26dc9bff61b0f23cccc595fdChris Forbes } 23155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 23165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 23175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis switch (type.opcode()) { 2318cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeStruct: { 2319cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski for (auto insn : *module) { 2320cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (insn.opcode() == spv::OpDecorate && insn.word(1) == type.word(1)) { 2321cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (insn.word(2) == spv::DecorationBlock) { 2322cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER || 2323cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; 2324cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else if (insn.word(2) == spv::DecorationBufferBlock) { 2325cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER || 2326cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC; 2327cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 23285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 23295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 23305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2331cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Invalid 2332cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return false; 2333cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 23345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2335cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeSampler: 2336cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return descriptor_type == VK_DESCRIPTOR_TYPE_SAMPLER || descriptor_type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 23375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2338cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeSampledImage: 2339cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER) { 2340cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Slight relaxation for some GLSL historical madness: samplerBuffer doesn't really have a sampler, and a texel 2341cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // buffer descriptor doesn't really provide one. Allow this slight mismatch. 2342cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski auto image_type = module->get_def(type.word(2)); 2343cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski auto dim = image_type.word(3); 2344cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski auto sampled = image_type.word(7); 2345cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return dim == spv::DimBuffer && sampled == 1; 2346cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 2347cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return descriptor_type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 23485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2349cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeImage: { 2350cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Many descriptor types backing image types-- depends on dimension and whether the image will be used with a sampler. 2351cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // SPIRV for Vulkan requires that sampled be 1 or 2 -- leaving the decision to runtime is unacceptable. 2352cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski auto dim = type.word(3); 2353cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski auto sampled = type.word(7); 23545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2355cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dim == spv::DimSubpassData) { 2356cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return descriptor_type == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; 2357cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else if (dim == spv::DimBuffer) { 2358cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (sampled == 1) { 2359cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; 2360cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else { 2361cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; 2362cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 2363cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else if (sampled == 1) { 2364cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return descriptor_type == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE || 2365cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski descriptor_type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 23665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 2367cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; 23685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 23695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 23705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2371cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // We shouldn't really see any other junk types -- but if we do, they're a mismatch. 2372cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 2373cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return false; // Mismatch 23745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 23755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 23765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 23774110a6be7a8a287d459475926985f71c27d01298Chris Forbesstatic bool require_feature(debug_report_data *report_data, VkBool32 feature, char const *feature_name) { 2378a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes if (!feature) { 2379bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 2380cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski SHADER_CHECKER_FEATURE_NOT_ENABLED, "SC", 2381cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Shader requires VkPhysicalDeviceFeatures::%s but is not " 2382cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "enabled on the device", 2383a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes feature_name)) { 2384a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes return false; 2385a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes } 2386a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes } 2387a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2388a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes return true; 2389a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes} 2390a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 239169f9a551bfb1fd5334950f9685c12c5adda23dfbChris Forbesstatic bool validate_shader_capabilities(debug_report_data *report_data, shader_module const *src, 239269f9a551bfb1fd5334950f9685c12c5adda23dfbChris Forbes VkPhysicalDeviceFeatures const *enabledFeatures) { 2393e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool pass = true; 2394a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2395a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes for (auto insn : *src) { 2396a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes if (insn.opcode() == spv::OpCapability) { 2397a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes switch (insn.word(1)) { 2398cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityMatrix: 2399cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityShader: 2400cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityInputAttachment: 2401cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilitySampled1D: 2402cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityImage1D: 2403cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilitySampledBuffer: 2404cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityImageBuffer: 2405cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityImageQuery: 2406cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityDerivativeControl: 2407cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Always supported by a Vulkan 1.0 implementation -- no feature bits. 2408cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2409a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2410cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityGeometry: 2411cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->geometryShader, "geometryShader"); 2412cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2413a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2414cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityTessellation: 2415cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->tessellationShader, "tessellationShader"); 2416cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2417a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2418cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityFloat64: 2419cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->shaderFloat64, "shaderFloat64"); 2420cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2421a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2422cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityInt64: 2423cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->shaderInt64, "shaderInt64"); 2424cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2425a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2426cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityTessellationPointSize: 2427cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityGeometryPointSize: 2428cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->shaderTessellationAndGeometryPointSize, 2429cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "shaderTessellationAndGeometryPointSize"); 2430cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2431a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2432cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityImageGatherExtended: 2433cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->shaderImageGatherExtended, "shaderImageGatherExtended"); 2434cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2435a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2436cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityStorageImageMultisample: 2437cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->shaderStorageImageMultisample, 2438cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "shaderStorageImageMultisample"); 2439cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2440a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2441cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityUniformBufferArrayDynamicIndexing: 2442cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->shaderUniformBufferArrayDynamicIndexing, 2443cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "shaderUniformBufferArrayDynamicIndexing"); 2444cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2445a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2446cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilitySampledImageArrayDynamicIndexing: 2447cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->shaderSampledImageArrayDynamicIndexing, 2448cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "shaderSampledImageArrayDynamicIndexing"); 2449cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2450a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2451cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityStorageBufferArrayDynamicIndexing: 2452cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->shaderStorageBufferArrayDynamicIndexing, 2453cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "shaderStorageBufferArrayDynamicIndexing"); 2454cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2455a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2456cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityStorageImageArrayDynamicIndexing: 2457cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->shaderStorageImageArrayDynamicIndexing, 2458cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "shaderStorageImageArrayDynamicIndexing"); 2459cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2460a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2461cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityClipDistance: 2462cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->shaderClipDistance, "shaderClipDistance"); 2463cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2464a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2465cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityCullDistance: 2466cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->shaderCullDistance, "shaderCullDistance"); 2467cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2468a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2469cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityImageCubeArray: 2470cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->imageCubeArray, "imageCubeArray"); 2471cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2472a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2473cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilitySampleRateShading: 2474cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->sampleRateShading, "sampleRateShading"); 2475cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2476a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2477cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilitySparseResidency: 2478cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->shaderResourceResidency, "shaderResourceResidency"); 2479cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2480a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2481cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityMinLod: 2482cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->shaderResourceMinLod, "shaderResourceMinLod"); 2483cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2484a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2485cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilitySampledCubeArray: 2486cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->imageCubeArray, "imageCubeArray"); 2487cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2488a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2489cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityImageMSArray: 2490cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->shaderStorageImageMultisample, 2491cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "shaderStorageImageMultisample"); 2492cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2493a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2494cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityStorageImageExtendedFormats: 2495cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->shaderStorageImageExtendedFormats, 2496cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "shaderStorageImageExtendedFormats"); 2497cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2498a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2499cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityInterpolationFunction: 2500cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->sampleRateShading, "sampleRateShading"); 2501cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2502a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2503cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityStorageImageReadWithoutFormat: 2504cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->shaderStorageImageReadWithoutFormat, 2505cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "shaderStorageImageReadWithoutFormat"); 2506cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2507a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2508cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityStorageImageWriteWithoutFormat: 2509cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->shaderStorageImageWriteWithoutFormat, 2510cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "shaderStorageImageWriteWithoutFormat"); 2511cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2512a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2513cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityMultiViewport: 2514cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass &= require_feature(report_data, enabledFeatures->multiViewport, "multiViewport"); 2515cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2516a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2517cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 2518cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 2519cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski SHADER_CHECKER_BAD_CAPABILITY, "SC", "Shader declares capability %u, not supported in Vulkan.", 2520cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski insn.word(1))) 2521cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pass = false; 2522cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2523a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes } 2524a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes } 2525a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes } 2526a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2527a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes return pass; 2528a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes} 2529a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2530b2a61f3cd17c68887759817059fa1872f1e1464aChris Forbesstatic uint32_t descriptor_type_to_reqs(shader_module const *module, uint32_t type_id) { 25312aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes auto type = module->get_def(type_id); 25322aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes 25332aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes while (true) { 25342aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes switch (type.opcode()) { 2535cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeArray: 2536cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeSampledImage: 2537cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski type = module->get_def(type.word(2)); 2538cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2539cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypePointer: 2540cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski type = module->get_def(type.word(3)); 2541cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2542cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeImage: { 2543cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski auto dim = type.word(3); 2544cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski auto arrayed = type.word(5); 2545cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski auto msaa = type.word(6); 2546cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski 2547cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski switch (dim) { 2548cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::Dim1D: 2549cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return arrayed ? DESCRIPTOR_REQ_VIEW_TYPE_1D_ARRAY : DESCRIPTOR_REQ_VIEW_TYPE_1D; 2550cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::Dim2D: 2551cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return (msaa ? DESCRIPTOR_REQ_MULTI_SAMPLE : DESCRIPTOR_REQ_SINGLE_SAMPLE) | 2552cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski (arrayed ? DESCRIPTOR_REQ_VIEW_TYPE_2D_ARRAY : DESCRIPTOR_REQ_VIEW_TYPE_2D); 2553cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::Dim3D: 2554cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return DESCRIPTOR_REQ_VIEW_TYPE_3D; 2555cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::DimCube: 2556cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return arrayed ? DESCRIPTOR_REQ_VIEW_TYPE_CUBE_ARRAY : DESCRIPTOR_REQ_VIEW_TYPE_CUBE; 2557cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::DimSubpassData: 2558cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return msaa ? DESCRIPTOR_REQ_MULTI_SAMPLE : DESCRIPTOR_REQ_SINGLE_SAMPLE; 2559cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: // buffer, etc. 2560cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return 0; 2561cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 25622aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes } 2563cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 2564cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return 0; 25652aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes } 25662aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes } 2567b2a61f3cd17c68887759817059fa1872f1e1464aChris Forbes} 2568b2a61f3cd17c68887759817059fa1872f1e1464aChris Forbes 2569cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskistatic bool validate_pipeline_shader_stage( 2570cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski debug_report_data *report_data, VkPipelineShaderStageCreateInfo const *pStage, PIPELINE_STATE *pipeline, 2571cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski shader_module **out_module, spirv_inst_iter *out_entrypoint, VkPhysicalDeviceFeatures const *enabledFeatures, 2572cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski std::unordered_map<VkShaderModule, std::unique_ptr<shader_module>> const &shaderModuleMap) { 2573e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool pass = true; 257469f9a551bfb1fd5334950f9685c12c5adda23dfbChris Forbes auto module_it = shaderModuleMap.find(pStage->module); 257569f9a551bfb1fd5334950f9685c12c5adda23dfbChris Forbes auto module = *out_module = module_it->second.get(); 257678be5018e238bd464b1f1c55138df277c0c18922Chris Forbes 2577c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski if (!module->has_valid_spirv) return pass; 2578c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski 257925002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Find the entrypoint 258078be5018e238bd464b1f1c55138df277c0c18922Chris Forbes auto entrypoint = *out_entrypoint = find_entrypoint(module, pStage->pName, pStage->stage); 258178be5018e238bd464b1f1c55138df277c0c18922Chris Forbes if (entrypoint == module->end()) { 25824f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, VALIDATION_ERROR_00510, 25834f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "SC", "No entrypoint found named `%s` for stage %s. %s.", pStage->pName, 25844f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes string_VkShaderStageFlagBits(pStage->stage), validation_error_map[VALIDATION_ERROR_00510])) { 2585cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return false; // no point continuing beyond here, any analysis is just going to be garbage. 258678be5018e238bd464b1f1c55138df277c0c18922Chris Forbes } 258778be5018e238bd464b1f1c55138df277c0c18922Chris Forbes } 258878be5018e238bd464b1f1c55138df277c0c18922Chris Forbes 258925002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Validate shader capabilities against enabled device features 2590557cdd5218accf51ca894a14b7c6eeeb733f5cbbChris Forbes pass &= validate_shader_capabilities(report_data, module, enabledFeatures); 259178be5018e238bd464b1f1c55138df277c0c18922Chris Forbes 259225002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Mark accessible ids 25933a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes auto accessible_ids = mark_accessible_ids(module, entrypoint); 259478be5018e238bd464b1f1c55138df277c0c18922Chris Forbes 259525002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Validate descriptor set layout against what the entrypoint actually uses 25963a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes auto descriptor_uses = collect_interface_by_descriptor_slot(report_data, module, accessible_ids); 259778be5018e238bd464b1f1c55138df277c0c18922Chris Forbes 25982e0eca3d6fad72a29ae072e3895e29a2d2d66476Tobin Ehlis auto pipelineLayout = pipeline->pipeline_layout; 2599ed399f66e0512ef077d0e0a7cb903248726d2424Chris Forbes 26000cfa9c3a1747749777581684536218f83c3977a9Chris Forbes pass &= validate_specialization_offsets(report_data, pStage); 2601416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis pass &= validate_push_constant_usage(report_data, &pipelineLayout.push_constant_ranges, module, accessible_ids, pStage->stage); 260278be5018e238bd464b1f1c55138df277c0c18922Chris Forbes 260325002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Validate descriptor use 260478be5018e238bd464b1f1c55138df277c0c18922Chris Forbes for (auto use : descriptor_uses) { 260578be5018e238bd464b1f1c55138df277c0c18922Chris Forbes // While validating shaders capture which slots are used by the pipeline 2606bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto &reqs = pipeline->active_slots[use.first.first][use.first.second]; 2607b2a61f3cd17c68887759817059fa1872f1e1464aChris Forbes reqs = descriptor_req(reqs | descriptor_type_to_reqs(module, use.second.type_id)); 260878be5018e238bd464b1f1c55138df277c0c18922Chris Forbes 260925002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Verify given pipelineLayout has requested setLayout with requested binding 2610c8268861aaa8f9c47920065d6323e4609e5081b0Tobin Ehlis const auto &binding = get_descriptor_binding(&pipelineLayout, use.first); 261178be5018e238bd464b1f1c55138df277c0c18922Chris Forbes unsigned required_descriptor_count; 261278be5018e238bd464b1f1c55138df277c0c18922Chris Forbes 261378be5018e238bd464b1f1c55138df277c0c18922Chris Forbes if (!binding) { 2614bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 2615bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SHADER_CHECKER_MISSING_DESCRIPTOR, "SC", 261678be5018e238bd464b1f1c55138df277c0c18922Chris Forbes "Shader uses descriptor slot %u.%u (used as type `%s`) but not declared in pipeline layout", 261778be5018e238bd464b1f1c55138df277c0c18922Chris Forbes use.first.first, use.first.second, describe_type(module, use.second.type_id).c_str())) { 2618e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves pass = false; 261978be5018e238bd464b1f1c55138df277c0c18922Chris Forbes } 262078be5018e238bd464b1f1c55138df277c0c18922Chris Forbes } else if (~binding->stageFlags & pStage->stage) { 2621bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 0, __LINE__, 2622cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski SHADER_CHECKER_DESCRIPTOR_NOT_ACCESSIBLE_FROM_STAGE, "SC", 2623cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Shader uses descriptor slot %u.%u (used " 2624cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "as type `%s`) but descriptor not " 2625cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "accessible from stage %s", 2626fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis use.first.first, use.first.second, describe_type(module, use.second.type_id).c_str(), 262778be5018e238bd464b1f1c55138df277c0c18922Chris Forbes string_VkShaderStageFlagBits(pStage->stage))) { 2628e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves pass = false; 262978be5018e238bd464b1f1c55138df277c0c18922Chris Forbes } 2630bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski } else if (!descriptor_type_match(module, use.second.type_id, binding->descriptorType, required_descriptor_count)) { 2631557cdd5218accf51ca894a14b7c6eeeb733f5cbbChris Forbes if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 2632cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski SHADER_CHECKER_DESCRIPTOR_TYPE_MISMATCH, "SC", 2633cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Type mismatch on descriptor slot " 2634cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%u.%u (used as type `%s`) but " 2635cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "descriptor of type %s", 2636fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis use.first.first, use.first.second, describe_type(module, use.second.type_id).c_str(), 263778be5018e238bd464b1f1c55138df277c0c18922Chris Forbes string_VkDescriptorType(binding->descriptorType))) { 2638e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves pass = false; 263978be5018e238bd464b1f1c55138df277c0c18922Chris Forbes } 264078be5018e238bd464b1f1c55138df277c0c18922Chris Forbes } else if (binding->descriptorCount < required_descriptor_count) { 2641557cdd5218accf51ca894a14b7c6eeeb733f5cbbChris Forbes if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 2642fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis SHADER_CHECKER_DESCRIPTOR_TYPE_MISMATCH, "SC", 264378be5018e238bd464b1f1c55138df277c0c18922Chris Forbes "Shader expects at least %u descriptors for binding %u.%u (used as type `%s`) but only %u provided", 264478be5018e238bd464b1f1c55138df277c0c18922Chris Forbes required_descriptor_count, use.first.first, use.first.second, 2645fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis describe_type(module, use.second.type_id).c_str(), binding->descriptorCount)) { 2646e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves pass = false; 264778be5018e238bd464b1f1c55138df277c0c18922Chris Forbes } 264878be5018e238bd464b1f1c55138df277c0c18922Chris Forbes } 264978be5018e238bd464b1f1c55138df277c0c18922Chris Forbes } 265078be5018e238bd464b1f1c55138df277c0c18922Chris Forbes 265125002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Validate use of input attachments against subpass structure 2652c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes if (pStage->stage == VK_SHADER_STAGE_FRAGMENT_BIT) { 26533a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes auto input_attachment_uses = collect_interface_by_input_attachment_index(report_data, module, accessible_ids); 2654c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes 2655c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes auto rpci = pipeline->render_pass_ci.ptr(); 2656c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes auto subpass = pipeline->graphicsPipelineCI.subpass; 2657c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes 2658c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes for (auto use : input_attachment_uses) { 2659c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes auto input_attachments = rpci->pSubpasses[subpass].pInputAttachments; 2660bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto index = (input_attachments && use.first < rpci->pSubpasses[subpass].inputAttachmentCount) 2661bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski ? input_attachments[use.first].attachment 2662bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski : VK_ATTACHMENT_UNUSED; 2663c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes 2664c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes if (index == VK_ATTACHMENT_UNUSED) { 2665c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 2666c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes SHADER_CHECKER_MISSING_INPUT_ATTACHMENT, "SC", 2667bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "Shader consumes input attachment index %d but not provided in subpass", use.first)) { 2668c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes pass = false; 2669c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes } 2670bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski } else if (get_format_type(rpci->pAttachments[index].format) != get_fundamental_type(module, use.second.type_id)) { 2671eeb9f6a27f1acc11e54080fb3bcda7b513b5c89fChris Forbes if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 2672eeb9f6a27f1acc11e54080fb3bcda7b513b5c89fChris Forbes SHADER_CHECKER_INPUT_ATTACHMENT_TYPE_MISMATCH, "SC", 2673bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "Subpass input attachment %u format of %s does not match type used in shader `%s`", use.first, 2674bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski string_VkFormat(rpci->pAttachments[index].format), describe_type(module, use.second.type_id).c_str())) { 2675eeb9f6a27f1acc11e54080fb3bcda7b513b5c89fChris Forbes pass = false; 2676eeb9f6a27f1acc11e54080fb3bcda7b513b5c89fChris Forbes } 2677eeb9f6a27f1acc11e54080fb3bcda7b513b5c89fChris Forbes } 2678c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes } 2679c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes } 2680c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes 268178be5018e238bd464b1f1c55138df277c0c18922Chris Forbes return pass; 268278be5018e238bd464b1f1c55138df277c0c18922Chris Forbes} 268378be5018e238bd464b1f1c55138df277c0c18922Chris Forbes 2684a61b537fcb6a4f7b92cd217b3964ad7a48109da1Tobin Ehlis// Validate that the shaders used by the given pipeline and store the active_slots 2685a61b537fcb6a4f7b92cd217b3964ad7a48109da1Tobin Ehlis// that are actually used by the pipeline into pPipeline->active_slots 2686cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskistatic bool validate_and_capture_pipeline_shader_state( 2687cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski debug_report_data *report_data, PIPELINE_STATE *pPipeline, VkPhysicalDeviceFeatures const *enabledFeatures, 2688cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski std::unordered_map<VkShaderModule, unique_ptr<shader_module>> const &shaderModuleMap) { 26896660d6f3e4e4c895063e8d99098162bd2f508b24Chris Forbes auto pCreateInfo = pPipeline->graphicsPipelineCI.ptr(); 26905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis int vertex_stage = get_shader_stage_id(VK_SHADER_STAGE_VERTEX_BIT); 26915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis int fragment_stage = get_shader_stage_id(VK_SHADER_STAGE_FRAGMENT_BIT); 26925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 26935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis shader_module *shaders[5]; 26945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis memset(shaders, 0, sizeof(shaders)); 26955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis spirv_inst_iter entrypoints[5]; 26965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis memset(entrypoints, 0, sizeof(entrypoints)); 26975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkPipelineVertexInputStateCreateInfo const *vi = 0; 2698e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool pass = true; 26995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 27005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->stageCount; i++) { 27016660d6f3e4e4c895063e8d99098162bd2f508b24Chris Forbes auto pStage = &pCreateInfo->pStages[i]; 270278be5018e238bd464b1f1c55138df277c0c18922Chris Forbes auto stage_id = get_shader_stage_id(pStage->stage); 2703bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pass &= validate_pipeline_shader_stage(report_data, pStage, pPipeline, &shaders[stage_id], &entrypoints[stage_id], 270469f9a551bfb1fd5334950f9685c12c5adda23dfbChris Forbes enabledFeatures, shaderModuleMap); 27055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 27065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2707d5365427feb4a6c16371ecb651afa37b89dabd96Chris Forbes // if the shader stages are no good individually, cross-stage validation is pointless. 2708cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!pass) return false; 2709b7476f4c4998ae20e579bd2d134667b71acdbf91Chris Forbes 27105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis vi = pCreateInfo->pVertexInputState; 27115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 27125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (vi) { 2713e4be8c69231df45752686575f22168b6d0fc5687Chris Forbes pass &= validate_vi_consistency(report_data, vi); 27145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 27155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2716c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski if (shaders[vertex_stage] && shaders[vertex_stage]->has_valid_spirv) { 2717e4be8c69231df45752686575f22168b6d0fc5687Chris Forbes pass &= validate_vi_against_vs_inputs(report_data, vi, shaders[vertex_stage], entrypoints[vertex_stage]); 27185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 27195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 27205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis int producer = get_shader_stage_id(VK_SHADER_STAGE_VERTEX_BIT); 27215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis int consumer = get_shader_stage_id(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT); 27225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 27235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis while (!shaders[producer] && producer != fragment_stage) { 27245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis producer++; 27255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis consumer++; 27265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 27275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 27285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (; producer != fragment_stage && consumer <= fragment_stage; consumer++) { 27295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(shaders[producer]); 2730c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski if (shaders[consumer] && shaders[consumer]->has_valid_spirv && shaders[producer]->has_valid_spirv) { 2731bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pass &= validate_interface_between_stages(report_data, shaders[producer], entrypoints[producer], 2732bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &shader_stage_attribs[producer], shaders[consumer], entrypoints[consumer], 2733bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &shader_stage_attribs[consumer]); 27345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 27355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis producer = consumer; 27365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 27375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 27385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2739c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski if (shaders[fragment_stage] && shaders[fragment_stage]->has_valid_spirv) { 2740e4be8c69231df45752686575f22168b6d0fc5687Chris Forbes pass &= validate_fs_outputs_against_render_pass(report_data, shaders[fragment_stage], entrypoints[fragment_stage], 27418da1edac0fbed13831b2f458f27c51e64d6210ffTobin Ehlis pPipeline->render_pass_ci.ptr(), pCreateInfo->subpass); 27425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 27435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 27445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return pass; 27455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 27465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 27474c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlisstatic bool validate_compute_pipeline(debug_report_data *report_data, PIPELINE_STATE *pPipeline, 27484c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis VkPhysicalDeviceFeatures const *enabledFeatures, 27494c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis std::unordered_map<VkShaderModule, unique_ptr<shader_module>> const &shaderModuleMap) { 27506660d6f3e4e4c895063e8d99098162bd2f508b24Chris Forbes auto pCreateInfo = pPipeline->computePipelineCI.ptr(); 275103857e826cdc6e8d814137fb3245596ca1cb7bc7Chris Forbes 275203857e826cdc6e8d814137fb3245596ca1cb7bc7Chris Forbes shader_module *module; 275303857e826cdc6e8d814137fb3245596ca1cb7bc7Chris Forbes spirv_inst_iter entrypoint; 275403857e826cdc6e8d814137fb3245596ca1cb7bc7Chris Forbes 2755bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski return validate_pipeline_shader_stage(report_data, &pCreateInfo->stage, pPipeline, &module, &entrypoint, enabledFeatures, 2756bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski shaderModuleMap); 275703857e826cdc6e8d814137fb3245596ca1cb7bc7Chris Forbes} 27585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Return Set node ptr for specified set or else NULL 27599a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehliscvdescriptorset::DescriptorSet *GetSetNode(const layer_data *dev_data, VkDescriptorSet set) { 276051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis auto set_it = dev_data->setMap.find(set); 276151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (set_it == dev_data->setMap.end()) { 27625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return NULL; 27635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 2764104ab082916e41467ef60baaab7a5a8b2e02c59cTobin Ehlis return set_it->second; 27655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 27665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2767eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young// For given pipeline, return number of MSAA samples, or one if MSAA disabled 27684c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlisstatic VkSampleCountFlagBits getNumSamples(PIPELINE_STATE const *pipe) { 2769ea8349eeee76ae2859c10870fd8bd9e60309eb28Chris Forbes if (pipe->graphicsPipelineCI.pMultisampleState != NULL && 2770ea8349eeee76ae2859c10870fd8bd9e60309eb28Chris Forbes VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO == pipe->graphicsPipelineCI.pMultisampleState->sType) { 2771eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young return pipe->graphicsPipelineCI.pMultisampleState->rasterizationSamples; 2772eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young } 2773eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young return VK_SAMPLE_COUNT_1_BIT; 2774eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young} 2775eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young 2776bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic void list_bits(std::ostream &s, uint32_t bits) { 2777b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes for (int i = 0; i < 32 && bits; i++) { 2778b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes if (bits & (1 << i)) { 2779b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes s << i; 2780b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes bits &= ~(1 << i); 2781b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes if (bits) { 2782b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes s << ","; 2783b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes } 2784b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes } 2785b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes } 2786b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes} 2787b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes 2788eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young// Validate draw-time state related to the PSO 278951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool ValidatePipelineDrawtimeState(layer_data const *dev_data, LAST_BOUND_STATE const &state, const GLOBAL_CB_NODE *pCB, 27904c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis PIPELINE_STATE const *pPipeline) { 2791eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young bool skip_call = false; 279229d196e071b2dc1db47702085469396f2b956820Chris Forbes 2793d79335137b414d5f89284a9ab3e014beb4ada3ebMike Weiblen // Verify vertex binding 279429d196e071b2dc1db47702085469396f2b956820Chris Forbes if (pPipeline->vertexBindingDescriptions.size() > 0) { 279529d196e071b2dc1db47702085469396f2b956820Chris Forbes for (size_t i = 0; i < pPipeline->vertexBindingDescriptions.size(); i++) { 2796312129ec52e6249aa453e27e6be17a8dab1e98b8Tobin Ehlis auto vertex_binding = pPipeline->vertexBindingDescriptions[i].binding; 2797312129ec52e6249aa453e27e6be17a8dab1e98b8Tobin Ehlis if ((pCB->currentDrawData.buffers.size() < (vertex_binding + 1)) || 2798312129ec52e6249aa453e27e6be17a8dab1e98b8Tobin Ehlis (pCB->currentDrawData.buffers[vertex_binding] == VK_NULL_HANDLE)) { 2799cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski skip_call |= 280051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 2801cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski DRAWSTATE_VTX_INDEX_OUT_OF_BOUNDS, "DS", 2802cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "The Pipeline State Object (0x%" PRIxLEAST64 2803cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ") expects that this Command Buffer's vertex binding Index %u " 2804cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "should be set via vkCmdBindVertexBuffers. This is because VkVertexInputBindingDescription struct " 2805cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "at index " PRINTF_SIZE_T_SPECIFIER " of pVertexBindingDescriptions has a binding value of %u.", 2806cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski (uint64_t)state.pipeline_state->pipeline, vertex_binding, i, vertex_binding); 280729d196e071b2dc1db47702085469396f2b956820Chris Forbes } 280829d196e071b2dc1db47702085469396f2b956820Chris Forbes } 280929d196e071b2dc1db47702085469396f2b956820Chris Forbes } else { 281058b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis if (!pCB->currentDrawData.buffers.empty() && !pCB->vertex_buffer_used) { 281151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 28125c288f35b2eab0dab95d18768235fef6ffd69b30Tobin Ehlis 0, __LINE__, DRAWSTATE_VTX_INDEX_OUT_OF_BOUNDS, "DS", 2813226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "Vertex buffers are bound to command buffer (0x%p" 28145c288f35b2eab0dab95d18768235fef6ffd69b30Tobin Ehlis ") but no vertex buffers are attached to this Pipeline State Object (0x%" PRIxLEAST64 ").", 2815226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis pCB->commandBuffer, (uint64_t)state.pipeline_state->pipeline); 281629d196e071b2dc1db47702085469396f2b956820Chris Forbes } 281729d196e071b2dc1db47702085469396f2b956820Chris Forbes } 281829d196e071b2dc1db47702085469396f2b956820Chris Forbes // If Viewport or scissors are dynamic, verify that dynamic count matches PSO count. 281929d196e071b2dc1db47702085469396f2b956820Chris Forbes // Skip check if rasterization is disabled or there is no viewport. 282029d196e071b2dc1db47702085469396f2b956820Chris Forbes if ((!pPipeline->graphicsPipelineCI.pRasterizationState || 282129d196e071b2dc1db47702085469396f2b956820Chris Forbes (pPipeline->graphicsPipelineCI.pRasterizationState->rasterizerDiscardEnable == VK_FALSE)) && 282229d196e071b2dc1db47702085469396f2b956820Chris Forbes pPipeline->graphicsPipelineCI.pViewportState) { 282329d196e071b2dc1db47702085469396f2b956820Chris Forbes bool dynViewport = isDynamic(pPipeline, VK_DYNAMIC_STATE_VIEWPORT); 282429d196e071b2dc1db47702085469396f2b956820Chris Forbes bool dynScissor = isDynamic(pPipeline, VK_DYNAMIC_STATE_SCISSOR); 2825b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes 282629d196e071b2dc1db47702085469396f2b956820Chris Forbes if (dynViewport) { 2827b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes auto requiredViewportsMask = (1 << pPipeline->graphicsPipelineCI.pViewportState->viewportCount) - 1; 2828b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes auto missingViewportMask = ~pCB->viewportMask & requiredViewportsMask; 2829b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes if (missingViewportMask) { 2830b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes std::stringstream ss; 2831b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes ss << "Dynamic viewport(s) "; 2832b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes list_bits(ss, missingViewportMask); 2833d79335137b414d5f89284a9ab3e014beb4ada3ebMike Weiblen ss << " are used by pipeline state object, but were not provided via calls to vkCmdSetViewport()."; 283451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, 2835bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski __LINE__, DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS", "%s", ss.str().c_str()); 283629d196e071b2dc1db47702085469396f2b956820Chris Forbes } 283729d196e071b2dc1db47702085469396f2b956820Chris Forbes } 2838b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes 283929d196e071b2dc1db47702085469396f2b956820Chris Forbes if (dynScissor) { 2840b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes auto requiredScissorMask = (1 << pPipeline->graphicsPipelineCI.pViewportState->scissorCount) - 1; 2841b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes auto missingScissorMask = ~pCB->scissorMask & requiredScissorMask; 2842b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes if (missingScissorMask) { 2843b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes std::stringstream ss; 2844b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes ss << "Dynamic scissor(s) "; 2845b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes list_bits(ss, missingScissorMask); 2846d79335137b414d5f89284a9ab3e014beb4ada3ebMike Weiblen ss << " are used by pipeline state object, but were not provided via calls to vkCmdSetScissor()."; 284751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, 2848bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski __LINE__, DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS", "%s", ss.str().c_str()); 284929d196e071b2dc1db47702085469396f2b956820Chris Forbes } 285029d196e071b2dc1db47702085469396f2b956820Chris Forbes } 285129d196e071b2dc1db47702085469396f2b956820Chris Forbes } 285229d196e071b2dc1db47702085469396f2b956820Chris Forbes 285329d196e071b2dc1db47702085469396f2b956820Chris Forbes // Verify that any MSAA request in PSO matches sample# in bound FB 285429d196e071b2dc1db47702085469396f2b956820Chris Forbes // Skip the check if rasterization is disabled. 285529d196e071b2dc1db47702085469396f2b956820Chris Forbes if (!pPipeline->graphicsPipelineCI.pRasterizationState || 285629d196e071b2dc1db47702085469396f2b956820Chris Forbes (pPipeline->graphicsPipelineCI.pRasterizationState->rasterizerDiscardEnable == VK_FALSE)) { 285729d196e071b2dc1db47702085469396f2b956820Chris Forbes VkSampleCountFlagBits pso_num_samples = getNumSamples(pPipeline); 285829d196e071b2dc1db47702085469396f2b956820Chris Forbes if (pCB->activeRenderPass) { 2859fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes auto const render_pass_info = pCB->activeRenderPass->createInfo.ptr(); 286029d196e071b2dc1db47702085469396f2b956820Chris Forbes const VkSubpassDescription *subpass_desc = &render_pass_info->pSubpasses[pCB->activeSubpass]; 286129d196e071b2dc1db47702085469396f2b956820Chris Forbes uint32_t i; 286276957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes unsigned subpass_num_samples = 0; 28630a7ed0466d3d3c6c71be07d66c200482d9a9d073Chris Forbes 286429d196e071b2dc1db47702085469396f2b956820Chris Forbes for (i = 0; i < subpass_desc->colorAttachmentCount; i++) { 286576957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes auto attachment = subpass_desc->pColorAttachments[i].attachment; 286676957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes if (attachment != VK_ATTACHMENT_UNUSED) 286776957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes subpass_num_samples |= (unsigned)render_pass_info->pAttachments[attachment].samples; 286829d196e071b2dc1db47702085469396f2b956820Chris Forbes } 28690a7ed0466d3d3c6c71be07d66c200482d9a9d073Chris Forbes 287076957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes if (subpass_desc->pDepthStencilAttachment && 287176957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes subpass_desc->pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) { 287276957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes auto attachment = subpass_desc->pDepthStencilAttachment->attachment; 287376957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes subpass_num_samples |= (unsigned)render_pass_info->pAttachments[attachment].samples; 287429d196e071b2dc1db47702085469396f2b956820Chris Forbes } 2875eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young 28760dc3fd4e57b8531638781daa01a2fb5d1048a6fbJamie Madill if (subpass_num_samples && static_cast<unsigned>(pso_num_samples) != subpass_num_samples) { 287729d196e071b2dc1db47702085469396f2b956820Chris Forbes skip_call |= 287851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 2879bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski reinterpret_cast<const uint64_t &>(pPipeline->pipeline), __LINE__, DRAWSTATE_NUM_SAMPLES_MISMATCH, "DS", 2880bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "Num samples mismatch! At draw-time in Pipeline (0x%" PRIxLEAST64 2881bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski ") with %u samples while current RenderPass (0x%" PRIxLEAST64 ") w/ %u samples!", 2882bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski reinterpret_cast<const uint64_t &>(pPipeline->pipeline), pso_num_samples, 2883bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski reinterpret_cast<const uint64_t &>(pCB->activeRenderPass->renderPass), subpass_num_samples); 2884eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young } 288529d196e071b2dc1db47702085469396f2b956820Chris Forbes } else { 288651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 2887bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski reinterpret_cast<const uint64_t &>(pPipeline->pipeline), __LINE__, DRAWSTATE_NUM_SAMPLES_MISMATCH, 2888bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "DS", "No active render pass found at draw-time in Pipeline (0x%" PRIxLEAST64 ")!", 288929d196e071b2dc1db47702085469396f2b956820Chris Forbes reinterpret_cast<const uint64_t &>(pPipeline->pipeline)); 2890eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young } 2891eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young } 2892528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis // Verify that PSO creation renderPass is compatible with active renderPass 2893528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis if (pCB->activeRenderPass) { 2894528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis std::string err_string; 2895a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis if ((pCB->activeRenderPass->renderPass != pPipeline->graphicsPipelineCI.renderPass) && 289651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis !verify_renderpass_compatibility(dev_data, pCB->activeRenderPass->createInfo.ptr(), pPipeline->render_pass_ci.ptr(), 2897528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis err_string)) { 2898528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis // renderPass that PSO was created with must be compatible with active renderPass that PSO is being used with 2899528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis skip_call |= 290051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 2901528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis reinterpret_cast<const uint64_t &>(pPipeline->pipeline), __LINE__, DRAWSTATE_RENDERPASS_INCOMPATIBLE, "DS", 2902cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "At Draw time the active render pass (0x%" PRIxLEAST64 2903cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ") is incompatible w/ gfx pipeline " 2904528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis "(0x%" PRIxLEAST64 ") that was created w/ render pass (0x%" PRIxLEAST64 ") due to: %s", 29056de0e43adfbd3c049252412d998524e7edbd3796Chris Forbes reinterpret_cast<uint64_t &>(pCB->activeRenderPass->renderPass), 29066de0e43adfbd3c049252412d998524e7edbd3796Chris Forbes reinterpret_cast<uint64_t const &>(pPipeline->pipeline), 2907528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis reinterpret_cast<const uint64_t &>(pPipeline->graphicsPipelineCI.renderPass), err_string.c_str()); 2908528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis } 2909c307df2953e6b023531a6ef7fd11e3ee2f2c58b0Chris Forbes 2910c307df2953e6b023531a6ef7fd11e3ee2f2c58b0Chris Forbes if (pPipeline->graphicsPipelineCI.subpass != pCB->activeSubpass) { 2911c307df2953e6b023531a6ef7fd11e3ee2f2c58b0Chris Forbes skip_call |= 291251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 2913c307df2953e6b023531a6ef7fd11e3ee2f2c58b0Chris Forbes reinterpret_cast<uint64_t const &>(pPipeline->pipeline), __LINE__, DRAWSTATE_RENDERPASS_INCOMPATIBLE, "DS", 2914c307df2953e6b023531a6ef7fd11e3ee2f2c58b0Chris Forbes "Pipeline was built for subpass %u but used in subpass %u", pPipeline->graphicsPipelineCI.subpass, 2915c307df2953e6b023531a6ef7fd11e3ee2f2c58b0Chris Forbes pCB->activeSubpass); 2916c307df2953e6b023531a6ef7fd11e3ee2f2c58b0Chris Forbes } 2917528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis } 291829d196e071b2dc1db47702085469396f2b956820Chris Forbes // TODO : Add more checks here 291929d196e071b2dc1db47702085469396f2b956820Chris Forbes 2920eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young return skip_call; 2921eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young} 2922eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young 29235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Validate overall state at the time of a draw call 292451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool ValidateDrawState(layer_data *dev_data, GLOBAL_CB_NODE *cb_node, const bool indexed, 29254f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes const VkPipelineBindPoint bind_point, const char *function, 29264f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes UNIQUE_VALIDATION_ERROR_CODE const msg_code) { 2927e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool result = false; 29281c130ea631a82716dc7334de17767536525f2292Tobin Ehlis auto const &state = cb_node->lastBound[bind_point]; 29294c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis PIPELINE_STATE *pPipe = state.pipeline_state; 293022fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis if (nullptr == pPipe) { 293122fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis result |= log_msg( 293251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 293322fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis DRAWSTATE_INVALID_PIPELINE, "DS", 293422fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis "At Draw/Dispatch time no valid VkPipeline is bound! This is illegal. Please bind one with vkCmdBindPipeline()."); 293522fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis // Early return as any further checks below will be busted w/o a pipeline 2936cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (result) return true; 293722fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis } 29383d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis // First check flag states 29391c130ea631a82716dc7334de17767536525f2292Tobin Ehlis if (VK_PIPELINE_BIND_POINT_GRAPHICS == bind_point) 294051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis result = validate_draw_state_flags(dev_data, cb_node, pPipe, indexed, msg_code); 29417a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis 29425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Now complete other state checks 294369b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis if (VK_NULL_HANDLE != state.pipeline_layout.layout) { 294422fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis string errorString; 294569b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis auto pipeline_layout = pPipe->pipeline_layout; 2946169c4506062f06d6676eb4da3c9e0437d1d9d659Chris Forbes 29471c130ea631a82716dc7334de17767536525f2292Tobin Ehlis for (const auto &set_binding_pair : pPipe->active_slots) { 29481c130ea631a82716dc7334de17767536525f2292Tobin Ehlis uint32_t setIndex = set_binding_pair.first; 294922fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis // If valid set is not bound throw an error 295022fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis if ((state.boundDescriptorSets.size() <= setIndex) || (!state.boundDescriptorSets[setIndex])) { 295151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis result |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 295222fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis DRAWSTATE_DESCRIPTOR_SET_NOT_BOUND, "DS", 2953bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "VkPipeline 0x%" PRIxLEAST64 " uses set #%u but that set is not bound.", 2954bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski (uint64_t)pPipe->pipeline, setIndex); 295551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis } else if (!verify_set_layout_compatibility(dev_data, state.boundDescriptorSets[setIndex], &pipeline_layout, setIndex, 295669b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis errorString)) { 295769b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis // Set is bound but not compatible w/ overlapping pipeline_layout from PSO 295871511c5a10533c910bfe62c3bcf58e2a4054e7acTobin Ehlis VkDescriptorSet setHandle = state.boundDescriptorSets[setIndex]->GetSet(); 295922fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis result |= 296051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, 296122fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis (uint64_t)setHandle, __LINE__, DRAWSTATE_PIPELINE_LAYOUTS_INCOMPATIBLE, "DS", 2962414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller "VkDescriptorSet (0x%" PRIxLEAST64 2963414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller ") bound as set #%u is not compatible with overlapping VkPipelineLayout 0x%" PRIxLEAST64 " due to: %s", 296469b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis reinterpret_cast<uint64_t &>(setHandle), setIndex, reinterpret_cast<uint64_t &>(pipeline_layout.layout), 296569b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis errorString.c_str()); 2966cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else { // Valid set is bound and layout compatible, validate that it's updated 296722fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis // Pull the set node 29681c130ea631a82716dc7334de17767536525f2292Tobin Ehlis cvdescriptorset::DescriptorSet *descriptor_set = state.boundDescriptorSets[setIndex]; 2969aa21bc3b3c5c7adfeb488fc80bdcb339d63615b8Tobin Ehlis // Gather active bindings 2970ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis std::unordered_set<uint32_t> active_bindings; 29711c130ea631a82716dc7334de17767536525f2292Tobin Ehlis for (auto binding : set_binding_pair.second) { 2972ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis active_bindings.insert(binding.first); 2973aa21bc3b3c5c7adfeb488fc80bdcb339d63615b8Tobin Ehlis } 297422fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis // Make sure set has been updated if it has no immutable samplers 297522fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis // If it has immutable samplers, we'll flag error later as needed depending on binding 29761c130ea631a82716dc7334de17767536525f2292Tobin Ehlis if (!descriptor_set->IsUpdated()) { 2977ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis for (auto binding : active_bindings) { 29781c130ea631a82716dc7334de17767536525f2292Tobin Ehlis if (!descriptor_set->GetImmutableSamplerPtrFromBinding(binding)) { 297951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis result |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 2980cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t)descriptor_set->GetSet(), 2981cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, DRAWSTATE_DESCRIPTOR_SET_NOT_UPDATED, "DS", 2982cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Descriptor Set 0x%" PRIxLEAST64 2983cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " bound but was never updated. It is now being used to draw so " 2984cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "this will result in undefined behavior.", 2985cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski (uint64_t)descriptor_set->GetSet()); 2986fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis } 29875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 29885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 29897433ab60c7ff16d37edb0f8b17b606ccd363e210Tobin Ehlis // Validate the draw-time state for this descriptor set 29907433ab60c7ff16d37edb0f8b17b606ccd363e210Tobin Ehlis std::string err_str; 29911c130ea631a82716dc7334de17767536525f2292Tobin Ehlis if (!descriptor_set->ValidateDrawState(set_binding_pair.second, state.dynamicOffsets[setIndex], &err_str)) { 29921c130ea631a82716dc7334de17767536525f2292Tobin Ehlis auto set = descriptor_set->GetSet(); 299351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis result |= log_msg( 299451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, 299551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis reinterpret_cast<const uint64_t &>(set), __LINE__, DRAWSTATE_DESCRIPTOR_SET_NOT_UPDATED, "DS", 299651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis "Descriptor set 0x%" PRIxLEAST64 " encountered the following validation error at %s() time: %s", 299751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis reinterpret_cast<const uint64_t &>(set), function, err_str.c_str()); 29987433ab60c7ff16d37edb0f8b17b606ccd363e210Tobin Ehlis } 29995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 300022fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis } 300122fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis } 3002eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young 3003eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young // Check general pipeline state that needs to be validated at drawtime 300451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (VK_PIPELINE_BIND_POINT_GRAPHICS == bind_point) result |= ValidatePipelineDrawtimeState(dev_data, state, cb_node, pPipe); 3005eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young 30065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 30075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 30085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 300951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic void UpdateDrawState(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, const VkPipelineBindPoint bind_point) { 30101c130ea631a82716dc7334de17767536525f2292Tobin Ehlis auto const &state = cb_state->lastBound[bind_point]; 3011ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis PIPELINE_STATE *pPipe = state.pipeline_state; 3012ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis if (VK_NULL_HANDLE != state.pipeline_layout.layout) { 30131c130ea631a82716dc7334de17767536525f2292Tobin Ehlis for (const auto &set_binding_pair : pPipe->active_slots) { 30141c130ea631a82716dc7334de17767536525f2292Tobin Ehlis uint32_t setIndex = set_binding_pair.first; 3015ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis // Pull the set node 30161c130ea631a82716dc7334de17767536525f2292Tobin Ehlis cvdescriptorset::DescriptorSet *descriptor_set = state.boundDescriptorSets[setIndex]; 3017ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis // Bind this set and its active descriptor resources to the command buffer 30181c130ea631a82716dc7334de17767536525f2292Tobin Ehlis descriptor_set->BindCommandBuffer(cb_state, set_binding_pair.second); 30197433ab60c7ff16d37edb0f8b17b606ccd363e210Tobin Ehlis // For given active slots record updated images & buffers 30201c130ea631a82716dc7334de17767536525f2292Tobin Ehlis descriptor_set->GetStorageUpdates(set_binding_pair.second, &cb_state->updateBuffers, &cb_state->updateImages); 3021ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis } 3022ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis } 302358b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis if (pPipe->vertexBindingDescriptions.size() > 0) { 302458b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis cb_state->vertex_buffer_used = true; 302558b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis } 3026ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis} 3027ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis 3028a27508babf63d50aea75883a3702979193c23683Mark Young// Validate HW line width capabilities prior to setting requested line width. 302951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool verifyLineWidth(layer_data *dev_data, DRAW_STATE_ERROR dsError, const uint64_t &target, float lineWidth) { 3030a27508babf63d50aea75883a3702979193c23683Mark Young bool skip_call = false; 3031a27508babf63d50aea75883a3702979193c23683Mark Young 3032a27508babf63d50aea75883a3702979193c23683Mark Young // First check to see if the physical device supports wide lines. 303351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if ((VK_FALSE == dev_data->enabled_features.wideLines) && (1.0f != lineWidth)) { 303451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, target, __LINE__, 3035cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski dsError, "DS", 3036cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Attempt to set lineWidth to %f but physical device wideLines feature " 3037cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "not supported/enabled so lineWidth must be 1.0f!", 3038a27508babf63d50aea75883a3702979193c23683Mark Young lineWidth); 3039a27508babf63d50aea75883a3702979193c23683Mark Young } else { 3040a27508babf63d50aea75883a3702979193c23683Mark Young // Otherwise, make sure the width falls in the valid range. 304151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if ((dev_data->phys_dev_properties.properties.limits.lineWidthRange[0] > lineWidth) || 304251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis (dev_data->phys_dev_properties.properties.limits.lineWidthRange[1] < lineWidth)) { 304351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, target, 3044cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, dsError, "DS", 3045cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Attempt to set lineWidth to %f but physical device limits line width " 3046cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "to between [%f, %f]!", 304751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis lineWidth, dev_data->phys_dev_properties.properties.limits.lineWidthRange[0], 304851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->phys_dev_properties.properties.limits.lineWidthRange[1]); 3049a27508babf63d50aea75883a3702979193c23683Mark Young } 3050a27508babf63d50aea75883a3702979193c23683Mark Young } 3051a27508babf63d50aea75883a3702979193c23683Mark Young 3052a27508babf63d50aea75883a3702979193c23683Mark Young return skip_call; 3053a27508babf63d50aea75883a3702979193c23683Mark Young} 3054a27508babf63d50aea75883a3702979193c23683Mark Young 30555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Verify that create state for a pipeline is valid 305651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool verifyPipelineCreateState(layer_data *dev_data, std::vector<PIPELINE_STATE *> pPipelines, int pipelineIndex) { 305783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 30585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 30594c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis PIPELINE_STATE *pPipeline = pPipelines[pipelineIndex]; 30605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 30615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // If create derivative bit is set, check that we've specified a base 30625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // pipeline correctly, and that the base pipeline was created to allow 30635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // derivatives. 30645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pPipeline->graphicsPipelineCI.flags & VK_PIPELINE_CREATE_DERIVATIVE_BIT) { 30654c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis PIPELINE_STATE *pBasePipeline = nullptr; 30665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!((pPipeline->graphicsPipelineCI.basePipelineHandle != VK_NULL_HANDLE) ^ 30675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (pPipeline->graphicsPipelineCI.basePipelineIndex != -1))) { 3068f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt // This check is a superset of VALIDATION_ERROR_00526 and VALIDATION_ERROR_00528 306951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 307083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS", 307183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis "Invalid Pipeline CreateInfo: exactly one of base pipeline index and handle must be specified"); 30725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (pPipeline->graphicsPipelineCI.basePipelineIndex != -1) { 30735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pPipeline->graphicsPipelineCI.basePipelineIndex >= pipelineIndex) { 307483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= 307551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 3076f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt VALIDATION_ERROR_00518, "DS", 3077f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt "Invalid Pipeline CreateInfo: base pipeline must occur earlier in array than derivative pipeline. %s", 3078f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt validation_error_map[VALIDATION_ERROR_00518]); 30795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 30805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pBasePipeline = pPipelines[pPipeline->graphicsPipelineCI.basePipelineIndex]; 30815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 30825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (pPipeline->graphicsPipelineCI.basePipelineHandle != VK_NULL_HANDLE) { 308351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis pBasePipeline = getPipelineState(dev_data, pPipeline->graphicsPipelineCI.basePipelineHandle); 30845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 30855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 30865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pBasePipeline && !(pBasePipeline->graphicsPipelineCI.flags & VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT)) { 308751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 308883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS", 308983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis "Invalid Pipeline CreateInfo: base pipeline does not allow derivatives."); 30905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 30915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 30925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 30935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pPipeline->graphicsPipelineCI.pColorBlendState != NULL) { 3094fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis const safe_VkPipelineColorBlendStateCreateInfo *color_blend_state = pPipeline->graphicsPipelineCI.pColorBlendState; 30959a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto const render_pass_info = GetRenderPassState(dev_data, pPipeline->graphicsPipelineCI.renderPass)->createInfo.ptr(); 3096fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis const VkSubpassDescription *subpass_desc = &render_pass_info->pSubpasses[pPipeline->graphicsPipelineCI.subpass]; 3097fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis if (color_blend_state->attachmentCount != subpass_desc->colorAttachmentCount) { 3098fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis skip_call |= log_msg( 309951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 3100fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis reinterpret_cast<const uint64_t &>(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_02109, "DS", 3101fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis "vkCreateGraphicsPipelines(): Render pass (0x%" PRIxLEAST64 3102fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis ") subpass %u has colorAttachmentCount of %u which doesn't match the pColorBlendState->attachmentCount of %u. %s", 3103fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis reinterpret_cast<const uint64_t &>(pPipeline->graphicsPipelineCI.renderPass), pPipeline->graphicsPipelineCI.subpass, 3104fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis subpass_desc->colorAttachmentCount, color_blend_state->attachmentCount, 3105fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis validation_error_map[VALIDATION_ERROR_02109]); 3106fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis } 310751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (!dev_data->enabled_features.independentBlend) { 31083d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis if (pPipeline->attachments.size() > 1) { 310926c548826ff0f83d12c769b51e7d6f76d1265c0eChris Forbes VkPipelineColorBlendAttachmentState *pAttachments = &pPipeline->attachments[0]; 3110c7bd67f06427b08ba65cdf2dd529c8234beebdd5Mark Lobodzinski for (size_t i = 1; i < pPipeline->attachments.size(); i++) { 311106811df0256552cd7da9d7297672af377463fc4aMark Mueller // Quoting the spec: "If [the independent blend] feature is not enabled, the VkPipelineColorBlendAttachmentState 311206811df0256552cd7da9d7297672af377463fc4aMark Mueller // settings for all color attachments must be identical." VkPipelineColorBlendAttachmentState contains 311306811df0256552cd7da9d7297672af377463fc4aMark Mueller // only attachment state, so memcmp is best suited for the comparison 311406811df0256552cd7da9d7297672af377463fc4aMark Mueller if (memcmp(static_cast<const void *>(pAttachments), static_cast<const void *>(&pAttachments[i]), 311506811df0256552cd7da9d7297672af377463fc4aMark Mueller sizeof(pAttachments[0]))) { 311651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 3117cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, VALIDATION_ERROR_01532, "DS", 3118cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Invalid Pipeline CreateInfo: If independent blend feature not " 3119cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "enabled, all elements of pAttachments must be identical. %s", 3120cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski validation_error_map[VALIDATION_ERROR_01532]); 312106811df0256552cd7da9d7297672af377463fc4aMark Mueller break; 3122c7bd67f06427b08ba65cdf2dd529c8234beebdd5Mark Lobodzinski } 31235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 31245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 31255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 312651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (!dev_data->enabled_features.logicOp && (pPipeline->graphicsPipelineCI.pColorBlendState->logicOpEnable != VK_FALSE)) { 312783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= 312851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 3129f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt VALIDATION_ERROR_01533, "DS", 3130f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt "Invalid Pipeline CreateInfo: If logic operations feature not enabled, logicOpEnable must be VK_FALSE. %s", 3131f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt validation_error_map[VALIDATION_ERROR_01533]); 31325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 31335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 31345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3135a61b537fcb6a4f7b92cd217b3964ad7a48109da1Tobin Ehlis // Ensure the subpass index is valid. If not, then validate_and_capture_pipeline_shader_state 31365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // produces nonsense errors that confuse users. Other layers should already 31375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // emit errors for renderpass being invalid. 31389a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto renderPass = GetRenderPassState(dev_data, pPipeline->graphicsPipelineCI.renderPass); 3139fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes if (renderPass && pPipeline->graphicsPipelineCI.subpass >= renderPass->createInfo.subpassCount) { 314051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 3141cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VALIDATION_ERROR_02122, "DS", 3142cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Invalid Pipeline CreateInfo State: Subpass index %u " 3143cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "is out of range for this renderpass (0..%u). %s", 3144f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt pPipeline->graphicsPipelineCI.subpass, renderPass->createInfo.subpassCount - 1, 3145f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt validation_error_map[VALIDATION_ERROR_02122]); 31465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 31475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 314851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (!GetDisables(dev_data)->shader_validation && 314951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis !validate_and_capture_pipeline_shader_state(dev_data->report_data, pPipeline, &dev_data->enabled_features, 315051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->shaderModuleMap)) { 315183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call = true; 31525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 315352156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes // Each shader's stage must be unique 315452156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes if (pPipeline->duplicate_shaders) { 315552156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes for (uint32_t stage = VK_SHADER_STAGE_VERTEX_BIT; stage & VK_SHADER_STAGE_ALL_GRAPHICS; stage <<= 1) { 315652156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes if (pPipeline->duplicate_shaders & stage) { 315751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, 315883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis __LINE__, DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS", 315983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis "Invalid Pipeline CreateInfo State: Multiple shaders provided for stage %s", 316083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis string_VkShaderStageFlagBits(VkShaderStageFlagBits(stage))); 316152156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes } 316252156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes } 316352156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes } 31645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // VS is required 31655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!(pPipeline->active_shaders & VK_SHADER_STAGE_VERTEX_BIT)) { 316651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 3167f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt VALIDATION_ERROR_00532, "DS", "Invalid Pipeline CreateInfo State: Vertex Shader required. %s", 3168f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt validation_error_map[VALIDATION_ERROR_00532]); 31695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 31705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Either both or neither TC/TE shaders should be defined 3171f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt if ((pPipeline->active_shaders & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) && 3172f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt !(pPipeline->active_shaders & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)) { 317351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 3174f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt VALIDATION_ERROR_00534, "DS", 3175f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt "Invalid Pipeline CreateInfo State: TE and TC shaders must be included or excluded as a pair. %s", 3176f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt validation_error_map[VALIDATION_ERROR_00534]); 3177f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt } 3178f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt if (!(pPipeline->active_shaders & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) && 3179f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt (pPipeline->active_shaders & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)) { 318051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 3181f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt VALIDATION_ERROR_00535, "DS", 3182f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt "Invalid Pipeline CreateInfo State: TE and TC shaders must be included or excluded as a pair. %s", 3183f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt validation_error_map[VALIDATION_ERROR_00535]); 31845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 31855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Compute shaders should be specified independent of Gfx shaders 3186f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt if (pPipeline->active_shaders & VK_SHADER_STAGE_COMPUTE_BIT) { 318751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 3188f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt VALIDATION_ERROR_00533, "DS", 3189f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt "Invalid Pipeline CreateInfo State: Do not specify Compute Shader for Gfx Pipeline. %s", 3190f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt validation_error_map[VALIDATION_ERROR_00533]); 31915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 31925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // VK_PRIMITIVE_TOPOLOGY_PATCH_LIST primitive topology is only valid for tessellation pipelines. 31935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Mismatching primitive topology and tessellation fails graphics pipeline creation. 31945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pPipeline->active_shaders & (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) && 3195ca546210846c65808717f8875deae39bd227c240Tobin Ehlis (!pPipeline->graphicsPipelineCI.pInputAssemblyState || 3196ca546210846c65808717f8875deae39bd227c240Tobin Ehlis pPipeline->graphicsPipelineCI.pInputAssemblyState->topology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST)) { 319751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 3198cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VALIDATION_ERROR_02099, "DS", 3199cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Invalid Pipeline CreateInfo State: " 3200cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "VK_PRIMITIVE_TOPOLOGY_PATCH_LIST must be set as IA " 3201cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "topology for tessellation pipelines. %s", 3202f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt validation_error_map[VALIDATION_ERROR_02099]); 32035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 3204ca546210846c65808717f8875deae39bd227c240Tobin Ehlis if (pPipeline->graphicsPipelineCI.pInputAssemblyState && 3205ca546210846c65808717f8875deae39bd227c240Tobin Ehlis pPipeline->graphicsPipelineCI.pInputAssemblyState->topology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST) { 32065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (~pPipeline->active_shaders & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) { 320751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 3208cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VALIDATION_ERROR_02100, "DS", 3209cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Invalid Pipeline CreateInfo State: " 3210cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "VK_PRIMITIVE_TOPOLOGY_PATCH_LIST primitive " 3211cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "topology is only valid for tessellation pipelines. %s", 3212f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt validation_error_map[VALIDATION_ERROR_02100]); 32135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 32145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 3215f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt 3216f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt if (pPipeline->graphicsPipelineCI.pTessellationState && 3217f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt ((pPipeline->graphicsPipelineCI.pTessellationState->patchControlPoints == 0) || 3218f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt (pPipeline->graphicsPipelineCI.pTessellationState->patchControlPoints > 321951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->phys_dev_properties.properties.limits.maxTessellationPatchSize))) { 322051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 3221cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VALIDATION_ERROR_01426, "DS", 3222cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Invalid Pipeline CreateInfo State: " 3223cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "VK_PRIMITIVE_TOPOLOGY_PATCH_LIST primitive " 3224cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "topology used with patchControlPoints value %u." 3225cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " patchControlPoints should be >0 and <=%u. %s", 3226f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt pPipeline->graphicsPipelineCI.pTessellationState->patchControlPoints, 322751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->phys_dev_properties.properties.limits.maxTessellationPatchSize, 3228f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt validation_error_map[VALIDATION_ERROR_01426]); 3229f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt } 3230f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt 32316b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen // If a rasterization state is provided... 3232a27508babf63d50aea75883a3702979193c23683Mark Young if (pPipeline->graphicsPipelineCI.pRasterizationState) { 32336b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen 32346b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen // Make sure that the line width conforms to the HW. 3235a27508babf63d50aea75883a3702979193c23683Mark Young if (!isDynamic(pPipeline, VK_DYNAMIC_STATE_LINE_WIDTH)) { 323651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call |= verifyLineWidth(dev_data, DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, 32376de0e43adfbd3c049252412d998524e7edbd3796Chris Forbes reinterpret_cast<uint64_t const &>(pPipeline->pipeline), 323883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis pPipeline->graphicsPipelineCI.pRasterizationState->lineWidth); 3239a27508babf63d50aea75883a3702979193c23683Mark Young } 32405dcdd90e54199dfeb29938a3a03d998397c22664Chris Forbes 32416b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen // If rasterization is enabled... 32426b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen if (pPipeline->graphicsPipelineCI.pRasterizationState->rasterizerDiscardEnable == VK_FALSE) { 32436b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen auto subpass_desc = renderPass ? &renderPass->createInfo.pSubpasses[pPipeline->graphicsPipelineCI.subpass] : nullptr; 32446b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen 32456b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen // If subpass uses a depth/stencil attachment, pDepthStencilState must be a pointer to a valid structure 32466b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen if (subpass_desc && subpass_desc->pDepthStencilAttachment && 32476b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen subpass_desc->pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) { 32486b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen if (!pPipeline->graphicsPipelineCI.pDepthStencilState) { 32496b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 32506b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, VALIDATION_ERROR_02115, "DS", 32516b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen "Invalid Pipeline CreateInfo State: pDepthStencilState is NULL when rasterization is " 32526b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen "enabled and subpass uses a depth/stencil attachment. %s", 32536b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen validation_error_map[VALIDATION_ERROR_02115]); 32546b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen } 32555dcdd90e54199dfeb29938a3a03d998397c22664Chris Forbes } 3256326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen 3257326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen // If subpass uses color attachments, pColorBlendState must be valid pointer 3258326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen if (subpass_desc) { 3259326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen uint32_t color_attachment_count = 0; 3260326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen for (uint32_t i = 0; i < subpass_desc->colorAttachmentCount; ++i) { 3261326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen if (subpass_desc->pColorAttachments[i].attachment != VK_ATTACHMENT_UNUSED) { 3262326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen ++color_attachment_count; 3263326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen } 3264326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen } 3265326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen if (color_attachment_count > 0 && pPipeline->graphicsPipelineCI.pColorBlendState == nullptr) { 3266326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 3267326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, VALIDATION_ERROR_02116, "DS", 3268326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen "Invalid Pipeline CreateInfo State: pColorBlendState is NULL when rasterization is " 3269326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen "enabled and subpass uses color attachments. %s", 3270326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen validation_error_map[VALIDATION_ERROR_02116]); 3271326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen } 3272326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen } 32735dcdd90e54199dfeb29938a3a03d998397c22664Chris Forbes } 32745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 32756b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen 327683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis return skip_call; 32775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 32785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 32795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Free the Pipeline nodes 328051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic void deletePipelines(layer_data *dev_data) { 328151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (dev_data->pipelineMap.size() <= 0) return; 328251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis for (auto &pipe_map_pair : dev_data->pipelineMap) { 3283ca546210846c65808717f8875deae39bd227c240Tobin Ehlis delete pipe_map_pair.second; 32845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 328551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->pipelineMap.clear(); 32865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 32875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 32885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Block of code at start here specifically for managing/tracking DSs 32895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 32905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Return Pool node ptr for specified pool or else NULL 32919a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisDESCRIPTOR_POOL_STATE *GetDescriptorPoolState(const layer_data *dev_data, const VkDescriptorPool pool) { 3292bb7ea477706f90eb2a72887f652795bc79f60ddeTobin Ehlis auto pool_it = dev_data->descriptorPoolMap.find(pool); 3293bb7ea477706f90eb2a72887f652795bc79f60ddeTobin Ehlis if (pool_it == dev_data->descriptorPoolMap.end()) { 32945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return NULL; 32955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 3296bb7ea477706f90eb2a72887f652795bc79f60ddeTobin Ehlis return pool_it->second; 32975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 32985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 32995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Validate that given set is valid and that it's not being used by an in-flight CmdBuffer 33005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// func_str is the name of the calling function 3301e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves// Return false if no errors occur 3302e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves// Return true if validation error occurs and callback returns true (to skip upcoming API call down the chain) 33030dcd0f7b37456e2e552d37094ba503c0d089b906Tobin Ehlisstatic bool validateIdleDescriptorSet(const layer_data *dev_data, VkDescriptorSet set, std::string func_str) { 3304cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.idle_descriptor_set) return false; 3305e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool skip_call = false; 33060dcd0f7b37456e2e552d37094ba503c0d089b906Tobin Ehlis auto set_node = dev_data->setMap.find(set); 33070dcd0f7b37456e2e552d37094ba503c0d089b906Tobin Ehlis if (set_node == dev_data->setMap.end()) { 33080dcd0f7b37456e2e552d37094ba503c0d089b906Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, 33095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (uint64_t)(set), __LINE__, DRAWSTATE_DOUBLE_DESTROY, "DS", 3310414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller "Cannot call %s() on descriptor set 0x%" PRIxLEAST64 " that has not been allocated.", func_str.c_str(), 33115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (uint64_t)(set)); 33125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 33131c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis // TODO : This covers various error cases so should pass error enum into this function and use passed in enum here 33145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (set_node->second->in_use.load()) { 33151c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis skip_call |= 33160dcd0f7b37456e2e552d37094ba503c0d089b906Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, 33171c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis (uint64_t)(set), __LINE__, VALIDATION_ERROR_00919, "DS", 33181c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis "Cannot call %s() on descriptor set 0x%" PRIxLEAST64 " that is in use by a command buffer. %s", 33191c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis func_str.c_str(), (uint64_t)(set), validation_error_map[VALIDATION_ERROR_00919]); 33205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 33215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 33225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return skip_call; 33235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 3324f80bf38f4fb3f177b3e1be11b7b1c5edcdbf7d9bChris Forbes 3325e6651096ed8f07840447783c66827cc16d659a49Tobin Ehlis// Remove set from setMap and delete the set 33269dd448578d59cb5ce692e833ba230783b30f3550Tobin Ehlisstatic void freeDescriptorSet(layer_data *dev_data, cvdescriptorset::DescriptorSet *descriptor_set) { 33279dd448578d59cb5ce692e833ba230783b30f3550Tobin Ehlis dev_data->setMap.erase(descriptor_set->GetSet()); 33289dd448578d59cb5ce692e833ba230783b30f3550Tobin Ehlis delete descriptor_set; 33299dd448578d59cb5ce692e833ba230783b30f3550Tobin Ehlis} 33305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Free all DS Pools including their Sets & related sub-structs 33315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// NOTE : Calls to this function should be wrapped in mutex 333251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic void deletePools(layer_data *dev_data) { 333351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (dev_data->descriptorPoolMap.size() <= 0) return; 333451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis for (auto ii = dev_data->descriptorPoolMap.begin(); ii != dev_data->descriptorPoolMap.end(); ++ii) { 3335c5f47f0a54e14c47d402aeabc6498d981ecda9ccTobin Ehlis // Remove this pools' sets from setMap and delete them 3336cb9ce9e05b8e939d3da35c64997c70049877f4feTobin Ehlis for (auto ds : (*ii).second->sets) { 333751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis freeDescriptorSet(dev_data, ds); 33385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 3339f13bee0887f3c3d1d597c82869864be3be836737Tobin Ehlis (*ii).second->sets.clear(); 33405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 334151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->descriptorPoolMap.clear(); 33425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 33435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 334451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic void clearDescriptorPool(layer_data *dev_data, const VkDevice device, const VkDescriptorPool pool, 33455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkDescriptorPoolResetFlags flags) { 33469a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DESCRIPTOR_POOL_STATE *pPool = GetDescriptorPoolState(dev_data, pool); 3347de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis // TODO: validate flags 3348de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis // For every set off of this pool, clear it, remove from setMap, and free cvdescriptorset::DescriptorSet 3349de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis for (auto ds : pPool->sets) { 335051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis freeDescriptorSet(dev_data, ds); 3351de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis } 3352de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis pPool->sets.clear(); 3353de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis // Reset available count for each type and available sets for this pool 3354de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis for (uint32_t i = 0; i < pPool->availableDescriptorTypeCount.size(); ++i) { 3355de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis pPool->availableDescriptorTypeCount[i] = pPool->maxDescriptorTypeCount[i]; 33565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 3357de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis pPool->availableSets = pPool->maxSets; 33585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 33595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 33605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// For given CB object, fetch associated CB Node from map 33619a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisGLOBAL_CB_NODE *GetCBNode(layer_data const *dev_data, const VkCommandBuffer cb) { 336251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis auto it = dev_data->commandBufferMap.find(cb); 336351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (it == dev_data->commandBufferMap.end()) { 33645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return NULL; 33655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 33665121a8dcacb23766ba4455b4eea429f0a3d62099Chris Forbes return it->second; 33675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 33685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Free all CB Nodes 33695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// NOTE : Calls to this function should be wrapped in mutex 337051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic void deleteCommandBuffers(layer_data *dev_data) { 337151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (dev_data->commandBufferMap.empty()) { 33725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return; 33735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 337451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis for (auto ii = dev_data->commandBufferMap.begin(); ii != dev_data->commandBufferMap.end(); ++ii) { 33755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis delete (*ii).second; 33765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 337751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->commandBufferMap.clear(); 33785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 33795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 338029f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis// If a renderpass is active, verify that the given command type is appropriate for current subpass state 338129f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlisbool ValidateCmdSubpassState(const layer_data *dev_data, const GLOBAL_CB_NODE *pCB, const CMD_TYPE cmd_type) { 3382cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!pCB->activeRenderPass) return false; 3383e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool skip_call = false; 3384d0d8e333806eaac08bdc87ddeff886dc2b0f09e7Tobin Ehlis if (pCB->activeSubpassContents == VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS && 3385d0d8e333806eaac08bdc87ddeff886dc2b0f09e7Tobin Ehlis (cmd_type != CMD_EXECUTECOMMANDS && cmd_type != CMD_NEXTSUBPASS && cmd_type != CMD_ENDRENDERPASS)) { 33865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 33875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis DRAWSTATE_INVALID_COMMAND_BUFFER, "DS", 33885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis "Commands cannot be called in a subpass using secondary command buffers."); 33895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (pCB->activeSubpassContents == VK_SUBPASS_CONTENTS_INLINE && cmd_type == CMD_EXECUTECOMMANDS) { 33905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 33915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis DRAWSTATE_INVALID_COMMAND_BUFFER, "DS", 33925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis "vkCmdExecuteCommands() cannot be called in a subpass using inline commands."); 33935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 33945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return skip_call; 33955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 33965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 339751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool checkGraphicsBit(const layer_data *dev_data, VkQueueFlags flags, const char *name) { 33985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!(flags & VK_QUEUE_GRAPHICS_BIT)) 339951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis return log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 34005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis DRAWSTATE_INVALID_COMMAND_BUFFER, "DS", 34015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis "Cannot call %s on a command buffer allocated from a pool without graphics capabilities.", name); 34025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 34035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 34045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 340551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool checkComputeBit(const layer_data *dev_data, VkQueueFlags flags, const char *name) { 34065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!(flags & VK_QUEUE_COMPUTE_BIT)) 340751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis return log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 34085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis DRAWSTATE_INVALID_COMMAND_BUFFER, "DS", 34095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis "Cannot call %s on a command buffer allocated from a pool without compute capabilities.", name); 34105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 34115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 34125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 341351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool checkGraphicsOrComputeBit(const layer_data *dev_data, VkQueueFlags flags, const char *name) { 34145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!((flags & VK_QUEUE_GRAPHICS_BIT) || (flags & VK_QUEUE_COMPUTE_BIT))) 341551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis return log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 34165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis DRAWSTATE_INVALID_COMMAND_BUFFER, "DS", 3417e4d82c37d6c861b388dbc80297c18d6255858cb4Dave Houlton "Cannot call %s on a command buffer allocated from a pool without graphics or compute capabilities.", name); 34185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 34195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 34205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3421ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinskistatic bool ReportInvalidCommandBuffer(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, const char *call_source) { 3422ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski bool skip = false; 3423ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski for (auto obj : cb_state->broken_bindings) { 3424ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski const char *type_str = object_type_to_string(obj.type); 3425ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski // Descriptor sets are a special case that can be either destroyed or updated to invalidate a CB 3426ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski const char *cause_str = (obj.type == VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT) ? "destroyed or updated" : "destroyed"; 3427ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 3428ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski reinterpret_cast<uint64_t &>(cb_state->commandBuffer), __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER, "DS", 3429ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski "You are adding %s to command buffer 0x%p that is invalid because bound %s 0x%" PRIxLEAST64 " was %s.", 3430ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski call_source, cb_state->commandBuffer, type_str, obj.handle, cause_str); 3431ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } 3432ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski return skip; 3433ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski} 3434ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski 3435623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski// Validate the given command being added to the specified cmd buffer, flagging errors if CB is not in the recording state or if 3436623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski// there's an issue with the Cmd ordering 3437946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinskibool ValidateCmd(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, const CMD_TYPE cmd, const char *caller_name) { 3438946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski bool skip = false; 3439946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski auto command_pool = GetCommandPoolNode(dev_data, cb_state->createInfo.commandPool); 3440946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (command_pool) { 3441946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski VkQueueFlags flags = dev_data->phys_dev_properties.queue_family_properties[command_pool->queueFamilyIndex].queueFlags; 34425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis switch (cmd) { 3443cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_BINDPIPELINE: 3444cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_BINDPIPELINEDELTA: 3445cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_BINDDESCRIPTORSETS: 3446cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_FILLBUFFER: 3447cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_CLEARCOLORIMAGE: 3448cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETEVENT: 3449cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_RESETEVENT: 3450cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_WAITEVENTS: 3451cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_BEGINQUERY: 3452cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_ENDQUERY: 3453cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_RESETQUERYPOOL: 3454cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_COPYQUERYPOOLRESULTS: 3455cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_WRITETIMESTAMP: 3456946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= checkGraphicsOrComputeBit(dev_data, flags, cmdTypeToString(cmd).c_str()); 3457cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3458cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETVIEWPORTSTATE: 3459cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETSCISSORSTATE: 3460cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETLINEWIDTHSTATE: 3461cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETDEPTHBIASSTATE: 3462cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETBLENDSTATE: 3463cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETDEPTHBOUNDSSTATE: 3464cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETSTENCILREADMASKSTATE: 3465cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETSTENCILWRITEMASKSTATE: 3466cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETSTENCILREFERENCESTATE: 3467cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_BINDINDEXBUFFER: 3468cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_BINDVERTEXBUFFER: 3469cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_DRAW: 3470cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_DRAWINDEXED: 3471cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_DRAWINDIRECT: 3472cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_DRAWINDEXEDINDIRECT: 3473cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_BLITIMAGE: 3474cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_CLEARATTACHMENTS: 3475cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_CLEARDEPTHSTENCILIMAGE: 3476cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_RESOLVEIMAGE: 3477cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_BEGINRENDERPASS: 3478cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_NEXTSUBPASS: 3479cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_ENDRENDERPASS: 3480946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= checkGraphicsBit(dev_data, flags, cmdTypeToString(cmd).c_str()); 3481cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3482cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_DISPATCH: 3483cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_DISPATCHINDIRECT: 3484946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= checkComputeBit(dev_data, flags, cmdTypeToString(cmd).c_str()); 3485cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3486cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_COPYBUFFER: 3487cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_COPYIMAGE: 3488cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_COPYBUFFERTOIMAGE: 3489cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_COPYIMAGETOBUFFER: 3490cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_CLONEIMAGEDATA: 3491cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_UPDATEBUFFER: 3492cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_PIPELINEBARRIER: 3493cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_EXECUTECOMMANDS: 3494cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_END: 3495cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3496cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 3497cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 34985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 34995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 3500946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (cb_state->state != CB_RECORDING) { 3501946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (cb_state->state == CB_INVALID) { 3502946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ReportInvalidCommandBuffer(dev_data, cb_state, caller_name); 3503ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } else { 3504946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 3505946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski reinterpret_cast<uint64_t &>(cb_state->commandBuffer), __LINE__, DRAWSTATE_NO_BEGIN_COMMAND_BUFFER, 3506946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "DS", "You must call vkBeginCommandBuffer() before this call to %s", caller_name); 3507ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } 35087651c2eb9fe152ba62921ed60454afd882357e2aTobin Ehlis } else { 3509946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ValidateCmdSubpassState(dev_data, cb_state, cmd); 35105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 3511946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski return skip; 35125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 351329f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis 35141ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlisvoid UpdateCmdBufferLastCmd(GLOBAL_CB_NODE *cb_state, const CMD_TYPE cmd) { 351529f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis if (cb_state->state == CB_RECORDING) { 351629f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis cb_state->last_cmd = cmd; 351729f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis } 351829f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis} 35197e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis// For given object struct return a ptr of BASE_NODE type for its wrapping struct 35207e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin EhlisBASE_NODE *GetStateStructPtrFromObject(layer_data *dev_data, VK_OBJECT object_struct) { 35217e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis BASE_NODE *base_ptr = nullptr; 35227e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis switch (object_struct.type) { 3523cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT: { 35249a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetSetNode(dev_data, reinterpret_cast<VkDescriptorSet &>(object_struct.handle)); 3525cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3526cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3527cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT: { 35289a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetSamplerState(dev_data, reinterpret_cast<VkSampler &>(object_struct.handle)); 3529cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3530cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3531cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT: { 35329a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetQueryPoolNode(dev_data, reinterpret_cast<VkQueryPool &>(object_struct.handle)); 3533cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3534cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3535cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT: { 3536cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski base_ptr = getPipelineState(dev_data, reinterpret_cast<VkPipeline &>(object_struct.handle)); 3537cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3538cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3539cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT: { 35409a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetBufferState(dev_data, reinterpret_cast<VkBuffer &>(object_struct.handle)); 3541cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3542cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3543cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT: { 35449a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetBufferViewState(dev_data, reinterpret_cast<VkBufferView &>(object_struct.handle)); 3545cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3546cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3547cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT: { 35489a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetImageState(dev_data, reinterpret_cast<VkImage &>(object_struct.handle)); 3549cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3550cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3551cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT: { 35529a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetImageViewState(dev_data, reinterpret_cast<VkImageView &>(object_struct.handle)); 3553cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3554cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3555cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT: { 35569a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetEventNode(dev_data, reinterpret_cast<VkEvent &>(object_struct.handle)); 3557cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3558cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3559cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT: { 35609a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetDescriptorPoolState(dev_data, reinterpret_cast<VkDescriptorPool &>(object_struct.handle)); 3561cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3562cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3563cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT: { 35649a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetCommandPoolNode(dev_data, reinterpret_cast<VkCommandPool &>(object_struct.handle)); 3565cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3566cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3567cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT: { 35689a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetFramebufferState(dev_data, reinterpret_cast<VkFramebuffer &>(object_struct.handle)); 3569cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3570cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3571cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT: { 35729a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetRenderPassState(dev_data, reinterpret_cast<VkRenderPass &>(object_struct.handle)); 3573cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3574cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3575cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT: { 35769a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetMemObjInfo(dev_data, reinterpret_cast<VkDeviceMemory &>(object_struct.handle)); 3577cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3578cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3579cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 3580cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // TODO : Any other objects to be handled here? 3581cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski assert(0); 3582cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3583bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis } 35847e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis return base_ptr; 35857e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis} 35867e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis 35877e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis// Tie the VK_OBJECT to the cmd buffer which includes: 35887e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis// Add object_binding to cmd buffer 35897e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis// Add cb_binding to object 35907e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlisstatic void addCommandBufferBinding(std::unordered_set<GLOBAL_CB_NODE *> *cb_bindings, VK_OBJECT obj, GLOBAL_CB_NODE *cb_node) { 35917e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis cb_bindings->insert(cb_node); 35927e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis cb_node->object_bindings.insert(obj); 35937e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis} 35947e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis// For a given object, if cb_node is in that objects cb_bindings, remove cb_node 35957e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlisstatic void removeCommandBufferBinding(layer_data *dev_data, VK_OBJECT const *object, GLOBAL_CB_NODE *cb_node) { 35967e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis BASE_NODE *base_obj = GetStateStructPtrFromObject(dev_data, *object); 3597cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (base_obj) base_obj->cb_bindings.erase(cb_node); 3598bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis} 35995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Reset the command buffer state 36005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Maintain the createInfo and set state to CB_NEW, but clear all other state 3601400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlisstatic void resetCB(layer_data *dev_data, const VkCommandBuffer cb) { 3602400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis GLOBAL_CB_NODE *pCB = dev_data->commandBufferMap[cb]; 36035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 3604b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine pCB->in_use.store(0); 3605347d4d3139a1e743ed85bd375c20fd35bbe68d74Chris Forbes pCB->last_cmd = CMD_NONE; 36065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Reset CB state (note that createInfo is not cleared) 36075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->commandBuffer = cb; 36085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis memset(&pCB->beginInfo, 0, sizeof(VkCommandBufferBeginInfo)); 36095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis memset(&pCB->inheritanceInfo, 0, sizeof(VkCommandBufferInheritanceInfo)); 36105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->numCmds = 0; 36115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis memset(pCB->drawCount, 0, NUM_DRAW_TYPES * sizeof(uint64_t)); 36125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->state = CB_NEW; 36135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->submitCount = 0; 36145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->status = 0; 3615b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes pCB->viewportMask = 0; 3616b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes pCB->scissorMask = 0; 361793c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski 361872d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis for (uint32_t i = 0; i < VK_PIPELINE_BIND_POINT_RANGE_SIZE; ++i) { 361972d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis pCB->lastBound[i].reset(); 362072d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis } 362193c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski 36225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis memset(&pCB->activeRenderPassBeginInfo, 0, sizeof(pCB->activeRenderPassBeginInfo)); 3623ee691f5c5fa87aac3750454d2bca2cb582e4e817Chris Forbes pCB->activeRenderPass = nullptr; 36245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->activeSubpassContents = VK_SUBPASS_CONTENTS_INLINE; 36255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->activeSubpass = 0; 3626e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis pCB->broken_bindings.clear(); 36275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->waitedEvents.clear(); 36285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->events.clear(); 3629c7e6bc41aa9c6e5a677b138b9459b252cd3bedf2Mark Lobodzinski pCB->writeEventsBeforeWait.clear(); 36305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->waitedEventsBeforeQueryReset.clear(); 36315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->queryToStateMap.clear(); 36325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->activeQueries.clear(); 36335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->startedQueries.clear(); 3634abfafae4ec5d76e520916b03d196e474e972c949Michael Lentine pCB->imageSubresourceMap.clear(); 36355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->imageLayoutMap.clear(); 36365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->eventToStageMap.clear(); 36375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->drawData.clear(); 36385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->currentDrawData.buffers.clear(); 363958b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis pCB->vertex_buffer_used = false; 36405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->primaryCommandBuffer = VK_NULL_HANDLE; 3641bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis // Make sure any secondaryCommandBuffers are removed from globalInFlight 3642bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis for (auto secondary_cb : pCB->secondaryCommandBuffers) { 3643bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis dev_data->globalInFlightCmdBuffers.erase(secondary_cb); 3644bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis } 36455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->secondaryCommandBuffers.clear(); 36467a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis pCB->updateImages.clear(); 36477a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis pCB->updateBuffers.clear(); 3648400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis clear_cmd_buf_and_mem_references(dev_data, pCB); 3649b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine pCB->eventUpdates.clear(); 3650d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine pCB->queryUpdates.clear(); 365193c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski 3652bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis // Remove object bindings 3653bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis for (auto obj : pCB->object_bindings) { 3654bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis removeCommandBufferBinding(dev_data, &obj, pCB); 3655bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis } 3656a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis pCB->object_bindings.clear(); 365793c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski // Remove this cmdBuffer's reference from each FrameBuffer's CB ref list 365893c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski for (auto framebuffer : pCB->framebuffers) { 36599a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto fb_state = GetFramebufferState(dev_data, framebuffer); 3660cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (fb_state) fb_state->cb_bindings.erase(pCB); 366193c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski } 366293c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski pCB->framebuffers.clear(); 36637003b38da5cc27a063af3c45080f3a35438283eeTobin Ehlis pCB->activeFramebuffer = VK_NULL_HANDLE; 36645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 36655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 36665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 36675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Set PSO-related status bits for CB, including dynamic state set via PSO 36684c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlisstatic void set_cb_pso_status(GLOBAL_CB_NODE *pCB, const PIPELINE_STATE *pPipe) { 36695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Account for any dynamic state not set via this PSO 3670ca546210846c65808717f8875deae39bd227c240Tobin Ehlis if (!pPipe->graphicsPipelineCI.pDynamicState || 3671cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski !pPipe->graphicsPipelineCI.pDynamicState->dynamicStateCount) { // All state is static 36724052946ae557337ff95f3725e879131b1c63f865Tobin Ehlis pCB->status |= CBSTATUS_ALL_STATE_SET; 36735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 36745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // First consider all state on 36755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Then unset any state that's noted as dynamic in PSO 36765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Finally OR that into CB statemask 36774052946ae557337ff95f3725e879131b1c63f865Tobin Ehlis CBStatusFlags psoDynStateMask = CBSTATUS_ALL_STATE_SET; 3678ca546210846c65808717f8875deae39bd227c240Tobin Ehlis for (uint32_t i = 0; i < pPipe->graphicsPipelineCI.pDynamicState->dynamicStateCount; i++) { 3679ca546210846c65808717f8875deae39bd227c240Tobin Ehlis switch (pPipe->graphicsPipelineCI.pDynamicState->pDynamicStates[i]) { 3680cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DYNAMIC_STATE_LINE_WIDTH: 3681cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski psoDynStateMask &= ~CBSTATUS_LINE_WIDTH_SET; 3682cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3683cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DYNAMIC_STATE_DEPTH_BIAS: 3684cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski psoDynStateMask &= ~CBSTATUS_DEPTH_BIAS_SET; 3685cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3686cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DYNAMIC_STATE_BLEND_CONSTANTS: 3687cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski psoDynStateMask &= ~CBSTATUS_BLEND_CONSTANTS_SET; 3688cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3689cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DYNAMIC_STATE_DEPTH_BOUNDS: 3690cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski psoDynStateMask &= ~CBSTATUS_DEPTH_BOUNDS_SET; 3691cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3692cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK: 3693cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski psoDynStateMask &= ~CBSTATUS_STENCIL_READ_MASK_SET; 3694cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3695cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DYNAMIC_STATE_STENCIL_WRITE_MASK: 3696cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski psoDynStateMask &= ~CBSTATUS_STENCIL_WRITE_MASK_SET; 3697cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3698cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DYNAMIC_STATE_STENCIL_REFERENCE: 3699cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski psoDynStateMask &= ~CBSTATUS_STENCIL_REFERENCE_SET; 3700cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3701cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 3702cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // TODO : Flag error here 3703cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 37045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 37055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 37065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->status |= psoDynStateMask; 37075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 37085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 37095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3710623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski// Flags validation error if the associated call is made inside a render pass. The apiName routine should ONLY be called outside a 3711623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski// render pass. 371251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisbool insideRenderPass(const layer_data *dev_data, GLOBAL_CB_NODE *pCB, const char *apiName, UNIQUE_VALIDATION_ERROR_CODE msgCode) { 3713e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool inside = false; 37145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB->activeRenderPass) { 371551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis inside = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 3716ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen (uint64_t)pCB->commandBuffer, __LINE__, msgCode, "DS", 3717ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen "%s: It is invalid to issue this call inside an active render pass (0x%" PRIxLEAST64 "). %s", apiName, 3718ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen (uint64_t)pCB->activeRenderPass->renderPass, validation_error_map[msgCode]); 37195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 37205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return inside; 37215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 37225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 37235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Flags validation error if the associated call is made outside a render pass. The apiName 37245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// routine should ONLY be called inside a render pass. 372551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisbool outsideRenderPass(const layer_data *dev_data, GLOBAL_CB_NODE *pCB, const char *apiName, UNIQUE_VALIDATION_ERROR_CODE msgCode) { 3726e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool outside = false; 37275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (((pCB->createInfo.level == VK_COMMAND_BUFFER_LEVEL_PRIMARY) && (!pCB->activeRenderPass)) || 37285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis ((pCB->createInfo.level == VK_COMMAND_BUFFER_LEVEL_SECONDARY) && (!pCB->activeRenderPass) && 37295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis !(pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT))) { 373051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis outside = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 3731ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen (uint64_t)pCB->commandBuffer, __LINE__, msgCode, "DS", 3732ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen "%s: This call must be issued inside an active render pass. %s", apiName, validation_error_map[msgCode]); 37335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 37345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return outside; 37355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 37365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3737f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbesstatic void init_core_validation(instance_layer_data *instance_data, const VkAllocationCallbacks *pAllocator) { 3738b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis layer_debug_actions(instance_data->report_data, instance_data->logging_callback, pAllocator, "lunarg_core_validation"); 37395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 37405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3741747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbesstatic void checkInstanceRegisterExtensions(const VkInstanceCreateInfo *pCreateInfo, instance_layer_data *instance_data) { 3742747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) { 3743747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SURFACE_EXTENSION_NAME)) 3744747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->surfaceExtensionEnabled = true; 3745747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_DISPLAY_EXTENSION_NAME)) 3746747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->displayExtensionEnabled = true; 3747747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_ANDROID_KHR 3748747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_ANDROID_SURFACE_EXTENSION_NAME)) 3749747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->androidSurfaceExtensionEnabled = true; 3750747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif 3751747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_MIR_KHR 3752747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_MIR_SURFACE_EXTENSION_NAME)) 3753747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->mirSurfaceExtensionEnabled = true; 3754747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif 3755747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_WAYLAND_KHR 3756747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME)) 3757747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->waylandSurfaceExtensionEnabled = true; 3758747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif 3759747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_WIN32_KHR 3760747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_WIN32_SURFACE_EXTENSION_NAME)) 3761747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->win32SurfaceExtensionEnabled = true; 3762747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif 3763747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_XCB_KHR 3764747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_XCB_SURFACE_EXTENSION_NAME)) 3765747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->xcbSurfaceExtensionEnabled = true; 3766747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif 3767747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_XLIB_KHR 3768747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_XLIB_SURFACE_EXTENSION_NAME)) 3769747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->xlibSurfaceExtensionEnabled = true; 3770747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif 3771747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes } 3772747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 3773747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 3774bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, 3775bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkInstance *pInstance) { 37765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO); 37775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 37785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(chain_info->u.pLayerInfo); 37795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr; 37805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance"); 3781cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED; 37825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 37835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Advance the link info for the next element on the chain 37845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext; 37855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 37865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance); 3787cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (result != VK_SUCCESS) return result; 37885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 378956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(*pInstance), instance_layer_data_map); 379056a5ba3e60a723781945959ffc10e2e215350de5Chia-I Wu instance_data->instance = *pInstance; 37919172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes layer_init_instance_dispatch_table(*pInstance, &instance_data->dispatch_table, fpGetInstanceProcAddr); 37929172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes instance_data->report_data = debug_report_create_instance( 37939172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes &instance_data->dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount, pCreateInfo->ppEnabledExtensionNames); 3794747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes checkInstanceRegisterExtensions(pCreateInfo, instance_data); 3795b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis init_core_validation(instance_data, pAllocator); 3796825ac70f99460ccb9494d34f93d8ee7ec303e5deMark Lobodzinski 37975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis ValidateLayerOrdering(*pCreateInfo); 37985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 37995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 38005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 38015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 380225002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// Hook DestroyInstance to remove tableInstanceMap entry 380389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) { 38045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODOSC : Shouldn't need any customization here 38055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dispatch_key key = get_dispatch_key(instance); 38065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TBD: Need any locking this early, in case this function is called at the 38075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // same time by more than one thread? 380856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(key, instance_layer_data_map); 38099172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes instance_data->dispatch_table.DestroyInstance(instance, pAllocator); 38105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3811b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 38125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Clean up logging callback, if any 38139172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes while (instance_data->logging_callback.size() > 0) { 38149172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes VkDebugReportCallbackEXT callback = instance_data->logging_callback.back(); 38159172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes layer_destroy_msg_callback(instance_data->report_data, callback, pAllocator); 38169172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes instance_data->logging_callback.pop_back(); 38175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 38185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 38199172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes layer_debug_report_destroy_instance(instance_data->report_data); 38205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis layer_data_map.erase(key); 38215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 38225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3823373469f006399d6b5204ee05db3b56beb168b36fMark Youngstatic void checkDeviceRegisterExtensions(const VkDeviceCreateInfo *pCreateInfo, VkDevice device) { 38245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t i; 3825bee1d36c54af112766d4e8552ad302f39290683aMark Lobodzinski // TBD: Need any locking, in case this function is called at the same time by more than one thread? 382656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 38275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->device_extensions.wsi_enabled = false; 3828c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young dev_data->device_extensions.wsi_display_swapchain_enabled = false; 3829bee1d36c54af112766d4e8552ad302f39290683aMark Lobodzinski dev_data->device_extensions.nv_glsl_shader_enabled = false; 38305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 38315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (i = 0; i < pCreateInfo->enabledExtensionCount; i++) { 3832bee1d36c54af112766d4e8552ad302f39290683aMark Lobodzinski if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SWAPCHAIN_EXTENSION_NAME) == 0) { 38335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->device_extensions.wsi_enabled = true; 3834bee1d36c54af112766d4e8552ad302f39290683aMark Lobodzinski } 3835bee1d36c54af112766d4e8552ad302f39290683aMark Lobodzinski if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_DISPLAY_SWAPCHAIN_EXTENSION_NAME) == 0) { 3836c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young dev_data->device_extensions.wsi_display_swapchain_enabled = true; 3837bee1d36c54af112766d4e8552ad302f39290683aMark Lobodzinski } 3838bee1d36c54af112766d4e8552ad302f39290683aMark Lobodzinski if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_NV_GLSL_SHADER_EXTENSION_NAME) == 0) { 3839bee1d36c54af112766d4e8552ad302f39290683aMark Lobodzinski dev_data->device_extensions.nv_glsl_shader_enabled = true; 3840bee1d36c54af112766d4e8552ad302f39290683aMark Lobodzinski } 38415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 38425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 38435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3844838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski// Verify that queue family has been properly requested 3845ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblenstatic bool ValidateRequestedQueueFamilyProperties(instance_layer_data *instance_data, VkPhysicalDevice gpu, 3846ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen const VkDeviceCreateInfo *create_info) { 3847838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski bool skip_call = false; 38489a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto physical_device_state = GetPhysicalDeviceState(instance_data, gpu); 3849838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski // First check is app has actually requested queueFamilyProperties 38504b293996aa6a9bd92ef1f0175eca4b0e8a9fd9fcChris Forbes if (!physical_device_state) { 3851bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski skip_call |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 3852bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_MUST_QUERY_COUNT, "DL", 3853838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski "Invalid call to vkCreateDevice() w/o first calling vkEnumeratePhysicalDevices()."); 38544b293996aa6a9bd92ef1f0175eca4b0e8a9fd9fcChris Forbes } else if (QUERY_DETAILS != physical_device_state->vkGetPhysicalDeviceQueueFamilyPropertiesState) { 3855838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski // TODO: This is not called out as an invalid use in the spec so make more informative recommendation. 38564b293996aa6a9bd92ef1f0175eca4b0e8a9fd9fcChris Forbes skip_call |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, 3857838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_INVALID_QUEUE_CREATE_REQUEST, 3858838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski "DL", "Call to vkCreateDevice() w/o first calling vkGetPhysicalDeviceQueueFamilyProperties()."); 3859838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski } else { 3860838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski // Check that the requested queue properties are valid 3861838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski for (uint32_t i = 0; i < create_info->queueCreateInfoCount; i++) { 3862838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski uint32_t requestedIndex = create_info->pQueueCreateInfos[i].queueFamilyIndex; 38637d8b6ab1b68c397da50bad43deb1fba389ebace7Chris Forbes if (requestedIndex >= physical_device_state->queue_family_properties.size()) { 3864838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski skip_call |= log_msg( 38654b293996aa6a9bd92ef1f0175eca4b0e8a9fd9fcChris Forbes instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, 3866838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski __LINE__, DEVLIMITS_INVALID_QUEUE_CREATE_REQUEST, "DL", 3867838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski "Invalid queue create request in vkCreateDevice(). Invalid queueFamilyIndex %u requested.", requestedIndex); 3868838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski } else if (create_info->pQueueCreateInfos[i].queueCount > 38697d8b6ab1b68c397da50bad43deb1fba389ebace7Chris Forbes physical_device_state->queue_family_properties[requestedIndex].queueCount) { 3870cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski skip_call |= log_msg( 3871cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, 3872cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, DEVLIMITS_INVALID_QUEUE_CREATE_REQUEST, "DL", 3873cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Invalid queue create request in vkCreateDevice(). QueueFamilyIndex %u only has %u queues, but " 3874cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "requested queueCount is %u.", 3875cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski requestedIndex, physical_device_state->queue_family_properties[requestedIndex].queueCount, 3876cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski create_info->pQueueCreateInfos[i].queueCount); 3877838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski } 3878838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski } 3879838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski } 3880838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski return skip_call; 3881838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski} 3882838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski 3883f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski// Verify that features have been queried and that they are available 3884bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic bool ValidateRequestedFeatures(instance_layer_data *dev_data, VkPhysicalDevice phys, 3885bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkPhysicalDeviceFeatures *requested_features) { 3886f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski bool skip_call = false; 3887f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski 38889a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto phys_device_state = GetPhysicalDeviceState(dev_data, phys); 38893bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes const VkBool32 *actual = reinterpret_cast<VkBool32 *>(&phys_device_state->features); 3890825ac70f99460ccb9494d34f93d8ee7ec303e5deMark Lobodzinski const VkBool32 *requested = reinterpret_cast<const VkBool32 *>(requested_features); 3891f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski // TODO : This is a nice, compact way to loop through struct, but a bad way to report issues 3892f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski // Need to provide the struct member name with the issue. To do that seems like we'll 3893f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski // have to loop through each struct member which should be done w/ codegen to keep in synch. 3894f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski uint32_t errors = 0; 3895f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski uint32_t total_bools = sizeof(VkPhysicalDeviceFeatures) / sizeof(VkBool32); 3896f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski for (uint32_t i = 0; i < total_bools; i++) { 3897f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski if (requested[i] > actual[i]) { 3898f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski // TODO: Add index to struct member name helper to be able to include a feature name 3899cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski skip_call |= 3900cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, 3901cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, DEVLIMITS_INVALID_FEATURE_REQUESTED, "DL", 3902cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "While calling vkCreateDevice(), requesting feature #%u in VkPhysicalDeviceFeatures struct, " 3903cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "which is not available on this device.", 3904cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski i); 3905f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski errors++; 3906f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski } 3907f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski } 39083bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes if (errors && (UNCALLED == phys_device_state->vkGetPhysicalDeviceFeaturesState)) { 3909f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski // If user didn't request features, notify them that they should 3910f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski // TODO: Verify this against the spec. I believe this is an invalid use of the API and should return an error 3911bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 3912bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski 0, __LINE__, DEVLIMITS_INVALID_FEATURE_REQUESTED, "DL", 3913bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "You requested features that are unavailable on this device. You should first query feature " 3914bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "availability by calling vkGetPhysicalDeviceFeatures()."); 3915f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski } 3916f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski return skip_call; 3917f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski} 3918f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski 391989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo, 392089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) { 392156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(gpu), instance_layer_data_map); 3922f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski bool skip_call = false; 3923f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski 3924f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski // Check that any requested features are available 3925f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski if (pCreateInfo->pEnabledFeatures) { 392656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis skip_call |= ValidateRequestedFeatures(instance_data, gpu, pCreateInfo->pEnabledFeatures); 3927f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski } 392856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis skip_call |= ValidateRequestedQueueFamilyProperties(instance_data, gpu, pCreateInfo); 3929f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski 39301d659b4113b77a95325df10d602a03f1e7abf8b7Mark Mueller if (skip_call) { 39311d659b4113b77a95325df10d602a03f1e7abf8b7Mark Mueller return VK_ERROR_VALIDATION_FAILED_EXT; 39321d659b4113b77a95325df10d602a03f1e7abf8b7Mark Mueller } 39331d659b4113b77a95325df10d602a03f1e7abf8b7Mark Mueller 39345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO); 39355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 39365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(chain_info->u.pLayerInfo); 39375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr; 39385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr; 393956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_data->instance, "vkCreateDevice"); 39405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (fpCreateDevice == NULL) { 39415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return VK_ERROR_INITIALIZATION_FAILED; 39425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 39435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 39445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Advance the link info for the next element on the chain 39455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext; 39465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 39475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice); 39485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (result != VK_SUCCESS) { 39495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 39505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 39515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3952b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 395356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *device_data = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map); 39545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 395556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis device_data->instance_data = instance_data; 39565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Setup device dispatch table 395756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_init_device_dispatch_table(*pDevice, &device_data->dispatch_table, fpGetDeviceProcAddr); 395856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis device_data->device = *pDevice; 3959ec85232c4d8d9ddf7d2ae57cb8203c5ab52c1106Mark Lobodzinski // Save PhysicalDevice handle 396056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis device_data->physical_device = gpu; 39615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 396256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis device_data->report_data = layer_debug_report_create_device(instance_data->report_data, *pDevice); 3963373469f006399d6b5204ee05db3b56beb168b36fMark Young checkDeviceRegisterExtensions(pCreateInfo, *pDevice); 39645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Get physical device limits for this device 396556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_data->dispatch_table.GetPhysicalDeviceProperties(gpu, &(device_data->phys_dev_properties.properties)); 39665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t count; 396756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_data->dispatch_table.GetPhysicalDeviceQueueFamilyProperties(gpu, &count, nullptr); 396856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis device_data->phys_dev_properties.queue_family_properties.resize(count); 396956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_data->dispatch_table.GetPhysicalDeviceQueueFamilyProperties( 397056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis gpu, &count, &device_data->phys_dev_properties.queue_family_properties[0]); 39715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODO: device limits should make sure these are compatible 39725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCreateInfo->pEnabledFeatures) { 397356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis device_data->enabled_features = *pCreateInfo->pEnabledFeatures; 39745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 397556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis memset(&device_data->enabled_features, 0, sizeof(VkPhysicalDeviceFeatures)); 39765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 3977e47dbc3f3340fa177d877a67b2adb76a570027e5Mark Lobodzinski // Store physical device properties and physical device mem limits into device layer_data structs 397856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_data->dispatch_table.GetPhysicalDeviceMemoryProperties(gpu, &device_data->phys_dev_mem_props); 397956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_data->dispatch_table.GetPhysicalDeviceProperties(gpu, &device_data->phys_dev_props); 3980b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 39815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 39825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis ValidateLayerOrdering(*pCreateInfo); 39835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 39845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 39855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 39865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 39875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// prototype 398889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) { 39895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODOSC : Shouldn't need any customization here 39903ec39aeb6d6f08fb1ee45f64f72543a710754c62Tobin Ehlis bool skip = false; 39915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dispatch_key key = get_dispatch_key(device); 399256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(key, layer_data_map); 39935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Free all the memory 3994b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 39955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis deletePipelines(dev_data); 3996fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes dev_data->renderPassMap.clear(); 39975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis deleteCommandBuffers(dev_data); 3998f13bee0887f3c3d1d597c82869864be3be836737Tobin Ehlis // This will also delete all sets in the pool & remove them from setMap 39995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis deletePools(dev_data); 4000f13bee0887f3c3d1d597c82869864be3be836737Tobin Ehlis // All sets should be removed 4001f13bee0887f3c3d1d597c82869864be3be836737Tobin Ehlis assert(dev_data->setMap.empty()); 4002a1e5173c89eb7f03e0434ad45ccd1471e722fa71Tobin Ehlis for (auto del_layout : dev_data->descriptorSetLayoutMap) { 4003a1e5173c89eb7f03e0434ad45ccd1471e722fa71Tobin Ehlis delete del_layout.second; 4004a1e5173c89eb7f03e0434ad45ccd1471e722fa71Tobin Ehlis } 4005fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis dev_data->descriptorSetLayoutMap.clear(); 40065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->imageViewMap.clear(); 40075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->imageMap.clear(); 40085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->imageSubresourceMap.clear(); 40095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->imageLayoutMap.clear(); 40105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->bufferViewMap.clear(); 40115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->bufferMap.clear(); 40121344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis // Queues persist until device is destroyed 40131344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis dev_data->queueMap.clear(); 40145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Report any memory leaks 40155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis layer_debug_report_destroy_device(device); 4016b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 40175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 40185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#if DISPATCH_MAP_DEBUG 4019414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller fprintf(stderr, "Device: 0x%p, key: 0x%p\n", device, key); 40205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#endif 40213ec39aeb6d6f08fb1ee45f64f72543a710754c62Tobin Ehlis if (!skip) { 40224a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyDevice(device, pAllocator); 40233ec39aeb6d6f08fb1ee45f64f72543a710754c62Tobin Ehlis layer_data_map.erase(key); 40245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 40255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 40265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 40275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}}; 40285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4029208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis// For given stage mask, if Geometry shader stage is on w/o GS being enabled, report geo_error_id 4030208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis// and if Tessellation Control or Evaluation shader stages are on w/o TS being enabled, report tess_error_id 4031208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlisstatic bool ValidateStageMaskGsTsEnables(layer_data *dev_data, VkPipelineStageFlags stageMask, const char *caller, 4032208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis UNIQUE_VALIDATION_ERROR_CODE geo_error_id, UNIQUE_VALIDATION_ERROR_CODE tess_error_id) { 4033208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis bool skip = false; 4034208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis if (!dev_data->enabled_features.geometryShader && (stageMask & VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT)) { 4035208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 4036cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski geo_error_id, "DL", 4037cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s call includes a stageMask with VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT bit set when " 4038cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "device does not have geometryShader feature enabled. %s", 4039208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis caller, validation_error_map[geo_error_id]); 4040208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis } 4041208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis if (!dev_data->enabled_features.tessellationShader && 4042208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis (stageMask & (VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT | VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT))) { 4043208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 4044cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski tess_error_id, "DL", 4045cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s call includes a stageMask with VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT " 4046cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "and/or VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT bit(s) set when device " 4047cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "does not have tessellationShader feature enabled. %s", 4048208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis caller, validation_error_map[tess_error_id]); 4049208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis } 4050208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis return skip; 4051208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis} 4052208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis 405351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour// Loop through bound objects and increment their in_use counts if increment parameter is true 405451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour// or flag an error if unknown objects are found 405551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourstatic bool ValidateOrIncrementBoundObjects(layer_data *dev_data, GLOBAL_CB_NODE const *cb_node, bool increment) { 4056162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis bool skip = false; 4057162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis DRAW_STATE_ERROR error_code = DRAWSTATE_NONE; 4058162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis BASE_NODE *base_obj = nullptr; 4059a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis for (auto obj : cb_node->object_bindings) { 4060a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis switch (obj.type) { 4061cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT: { 40629a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_obj = GetSetNode(dev_data, reinterpret_cast<VkDescriptorSet &>(obj.handle)); 4063cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski error_code = DRAWSTATE_INVALID_DESCRIPTOR_SET; 4064cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 4065cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 4066cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT: { 40679a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_obj = GetSamplerState(dev_data, reinterpret_cast<VkSampler &>(obj.handle)); 4068cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski error_code = DRAWSTATE_INVALID_SAMPLER; 4069cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 4070cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 4071cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT: { 40729a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_obj = GetQueryPoolNode(dev_data, reinterpret_cast<VkQueryPool &>(obj.handle)); 4073cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski error_code = DRAWSTATE_INVALID_QUERY_POOL; 4074cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 4075cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 4076cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT: { 4077cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski base_obj = getPipelineState(dev_data, reinterpret_cast<VkPipeline &>(obj.handle)); 4078cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski error_code = DRAWSTATE_INVALID_PIPELINE; 4079cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 4080cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 4081cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT: { 40829a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_obj = GetBufferState(dev_data, reinterpret_cast<VkBuffer &>(obj.handle)); 4083cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski error_code = DRAWSTATE_INVALID_BUFFER; 4084cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 4085cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 4086cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT: { 40879a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_obj = GetBufferViewState(dev_data, reinterpret_cast<VkBufferView &>(obj.handle)); 4088cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski error_code = DRAWSTATE_INVALID_BUFFER_VIEW; 4089cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 4090cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 4091cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT: { 40929a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_obj = GetImageState(dev_data, reinterpret_cast<VkImage &>(obj.handle)); 4093cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski error_code = DRAWSTATE_INVALID_IMAGE; 4094cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 4095cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 4096cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT: { 40979a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_obj = GetImageViewState(dev_data, reinterpret_cast<VkImageView &>(obj.handle)); 4098cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski error_code = DRAWSTATE_INVALID_IMAGE_VIEW; 4099cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 4100cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 4101cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT: { 41029a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_obj = GetEventNode(dev_data, reinterpret_cast<VkEvent &>(obj.handle)); 4103cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski error_code = DRAWSTATE_INVALID_EVENT; 4104cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 4105cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 4106cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT: { 41079a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_obj = GetDescriptorPoolState(dev_data, reinterpret_cast<VkDescriptorPool &>(obj.handle)); 4108cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski error_code = DRAWSTATE_INVALID_DESCRIPTOR_POOL; 4109cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 4110cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 4111cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT: { 41129a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_obj = GetCommandPoolNode(dev_data, reinterpret_cast<VkCommandPool &>(obj.handle)); 4113cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski error_code = DRAWSTATE_INVALID_COMMAND_POOL; 4114cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 4115cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 4116cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT: { 41179a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_obj = GetFramebufferState(dev_data, reinterpret_cast<VkFramebuffer &>(obj.handle)); 4118cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski error_code = DRAWSTATE_INVALID_FRAMEBUFFER; 4119cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 4120cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 4121cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT: { 41229a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_obj = GetRenderPassState(dev_data, reinterpret_cast<VkRenderPass &>(obj.handle)); 4123cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski error_code = DRAWSTATE_INVALID_RENDERPASS; 4124cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 4125cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 4126cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT: { 41279a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_obj = GetMemObjInfo(dev_data, reinterpret_cast<VkDeviceMemory &>(obj.handle)); 4128cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski error_code = DRAWSTATE_INVALID_DEVICE_MEMORY; 4129cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 4130cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 4131cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 4132cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // TODO : Merge handling of other objects types into this code 4133cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 4134a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis } 413551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (base_obj && increment) { 413651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour base_obj->in_use.fetch_add(1); 413751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } else if (!base_obj && !increment) { 4138162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis skip |= 4139162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, obj.type, obj.handle, __LINE__, error_code, "DS", 4140162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis "Cannot submit cmd buffer using deleted %s 0x%" PRIx64 ".", object_type_to_string(obj.type), obj.handle); 4141162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis } 4142a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis } 4143162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis return skip; 4144a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis} 41455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Track which resources are in-flight by atomically incrementing their "in_use" count 414651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourstatic void incrementResources(layer_data *dev_data, GLOBAL_CB_NODE *cb_node) { 414751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour cb_node->submitCount++; 41489a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis cb_node->in_use.fetch_add(1); 41499a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis dev_data->globalInFlightCmdBuffers.insert(cb_node->commandBuffer); 4150a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes 4151a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis // First Increment for all "generic" objects bound to cmd buffer, followed by special-case objects below 415251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour ValidateOrIncrementBoundObjects(dev_data, cb_node, true); 4153a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis // TODO : We should be able to remove the NULL look-up checks from the code below as long as 4154a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis // all the corresponding cases are verified to cause CB_INVALID state and the CB_INVALID state 4155a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis // should then be flagged prior to calling this function 41569a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis for (auto drawDataElement : cb_node->drawData) { 41575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto buffer : drawDataElement.buffers) { 41589a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto buffer_state = GetBufferState(dev_data, buffer); 415951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (buffer_state) { 41605cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis buffer_state->in_use.fetch_add(1); 41615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 41625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 41635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 41649a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis for (auto event : cb_node->writeEventsBeforeWait) { 41659a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto event_state = GetEventNode(dev_data, event); 4166cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (event_state) event_state->write_in_use++; 4167c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine } 41685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 41695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4170b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis// Note: This function assumes that the global lock is held by the calling thread. 4171b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis// For the given queue, verify the queue state up to the given seq number. 4172b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis// Currently the only check is to make sure that if there are events to be waited on prior to 4173b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis// a QueryReset, make sure that all such events have been signalled. 417436c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlisstatic bool VerifyQueueStateToSeq(layer_data *dev_data, QUEUE_STATE *queue, uint64_t seq) { 4175b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis bool skip = false; 4176b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis auto queue_seq = queue->seq; 417792b1701c552e96e96fdbbb77e4b106a9526f3b8cTobin Ehlis std::unordered_map<VkQueue, uint64_t> other_queue_seqs; 417892b1701c552e96e96fdbbb77e4b106a9526f3b8cTobin Ehlis auto sub_it = queue->submissions.begin(); 4179b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis while (queue_seq < seq) { 418092b1701c552e96e96fdbbb77e4b106a9526f3b8cTobin Ehlis for (auto &wait : sub_it->waitSemaphores) { 418192b1701c552e96e96fdbbb77e4b106a9526f3b8cTobin Ehlis auto &last_seq = other_queue_seqs[wait.queue]; 418292b1701c552e96e96fdbbb77e4b106a9526f3b8cTobin Ehlis last_seq = std::max(last_seq, wait.seq); 418392b1701c552e96e96fdbbb77e4b106a9526f3b8cTobin Ehlis } 418492b1701c552e96e96fdbbb77e4b106a9526f3b8cTobin Ehlis for (auto cb : sub_it->cbs) { 41859a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, cb); 4186b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis if (cb_node) { 4187b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis for (auto queryEventsPair : cb_node->waitedEventsBeforeQueryReset) { 4188b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis for (auto event : queryEventsPair.second) { 418992b1701c552e96e96fdbbb77e4b106a9526f3b8cTobin Ehlis if (dev_data->eventMap[event].needsSignaled) { 419092b1701c552e96e96fdbbb77e4b106a9526f3b8cTobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 4191b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, 0, DRAWSTATE_INVALID_QUERY, "DS", 4192b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis "Cannot get query results on queryPool 0x%" PRIx64 4193b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis " with index %d which was guarded by unsignaled event 0x%" PRIx64 ".", 4194b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis (uint64_t)(queryEventsPair.first.pool), queryEventsPair.first.index, (uint64_t)(event)); 4195b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis } 4196b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis } 4197b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine } 4198b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine } 4199b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine } 420092b1701c552e96e96fdbbb77e4b106a9526f3b8cTobin Ehlis sub_it++; 4201b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis queue_seq++; 4202b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine } 420392b1701c552e96e96fdbbb77e4b106a9526f3b8cTobin Ehlis for (auto qs : other_queue_seqs) { 42049a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis skip |= VerifyQueueStateToSeq(dev_data, GetQueueState(dev_data, qs.first), qs.second); 420592b1701c552e96e96fdbbb77e4b106a9526f3b8cTobin Ehlis } 4206b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis return skip; 4207b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis} 4208b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis 4209b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis// When the given fence is retired, verify outstanding queue operations through the point of the fence 4210b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlisstatic bool VerifyQueueStateToFence(layer_data *dev_data, VkFence fence) { 42119a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto fence_state = GetFenceNode(dev_data, fence); 4212b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis if (VK_NULL_HANDLE != fence_state->signaler.first) { 42139a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis return VerifyQueueStateToSeq(dev_data, GetQueueState(dev_data, fence_state->signaler.first), fence_state->signaler.second); 4214b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis } 4215b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis return false; 4216b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine} 42177d33205c3aa4aba751a2c07f956634aac616f916Chris Forbes 42187d33205c3aa4aba751a2c07f956634aac616f916Chris Forbes// TODO: nuke this completely. 4219b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine// Decrement cmd_buffer in_use and if it goes to 0 remove cmd_buffer from globalInFlightCmdBuffers 4220b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentinestatic inline void removeInFlightCmdBuffer(layer_data *dev_data, VkCommandBuffer cmd_buffer) { 4221b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine // Pull it off of global list initially, but if we find it in any other queue list, add it back in 42229a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, cmd_buffer); 4223b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine pCB->in_use.fetch_sub(1); 4224b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine if (!pCB->in_use.load()) { 4225b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine dev_data->globalInFlightCmdBuffers.erase(cmd_buffer); 4226b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine } 4227b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine} 4228b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine 4229a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis// Decrement in-use count for objects bound to command buffer 42302f8cbf3b166e175174877a59929902e005953d6dTobin Ehlisstatic void DecrementBoundResources(layer_data *dev_data, GLOBAL_CB_NODE const *cb_node) { 423100e8ce2e6c1c191758f7b7c15eeaf350e5b4a3b6Tobin Ehlis BASE_NODE *base_obj = nullptr; 4232a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis for (auto obj : cb_node->object_bindings) { 42337e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis base_obj = GetStateStructPtrFromObject(dev_data, obj); 423400e8ce2e6c1c191758f7b7c15eeaf350e5b4a3b6Tobin Ehlis if (base_obj) { 423500e8ce2e6c1c191758f7b7c15eeaf350e5b4a3b6Tobin Ehlis base_obj->in_use.fetch_sub(1); 423600e8ce2e6c1c191758f7b7c15eeaf350e5b4a3b6Tobin Ehlis } 4237a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis } 4238a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis} 4239da8f07baf262972eb3e719fa07b073c180dff157Chris Forbes 424036c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlisstatic void RetireWorkOnQueue(layer_data *dev_data, QUEUE_STATE *pQueue, uint64_t seq) { 42419867daedbf52debc77d6568162ee21e071699b80Chris Forbes std::unordered_map<VkQueue, uint64_t> otherQueueSeqs; 42429867daedbf52debc77d6568162ee21e071699b80Chris Forbes 42439867daedbf52debc77d6568162ee21e071699b80Chris Forbes // Roll this queue forward, one submission at a time. 42449867daedbf52debc77d6568162ee21e071699b80Chris Forbes while (pQueue->seq < seq) { 4245bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto &submission = pQueue->submissions.front(); 42469867daedbf52debc77d6568162ee21e071699b80Chris Forbes 4247bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski for (auto &wait : submission.waitSemaphores) { 42489a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pSemaphore = GetSemaphoreNode(dev_data, wait.semaphore); 4249c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski if (pSemaphore) { 4250c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski pSemaphore->in_use.fetch_sub(1); 4251c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski } 4252bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto &lastSeq = otherQueueSeqs[wait.queue]; 42539867daedbf52debc77d6568162ee21e071699b80Chris Forbes lastSeq = std::max(lastSeq, wait.seq); 4254da8f07baf262972eb3e719fa07b073c180dff157Chris Forbes } 4255cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes 4256bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski for (auto &semaphore : submission.signalSemaphores) { 42579a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pSemaphore = GetSemaphoreNode(dev_data, semaphore); 4258c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski if (pSemaphore) { 4259c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski pSemaphore->in_use.fetch_sub(1); 4260c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski } 42619867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 4262cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes 42639867daedbf52debc77d6568162ee21e071699b80Chris Forbes for (auto cb : submission.cbs) { 42649a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, cb); 4265c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski if (!cb_node) { 4266c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski continue; 4267c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski } 4268a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis // First perform decrement on general case bound objects 42699a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis DecrementBoundResources(dev_data, cb_node); 42709a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis for (auto drawDataElement : cb_node->drawData) { 42719867daedbf52debc77d6568162ee21e071699b80Chris Forbes for (auto buffer : drawDataElement.buffers) { 42729a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto buffer_state = GetBufferState(dev_data, buffer); 42735cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis if (buffer_state) { 42745cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis buffer_state->in_use.fetch_sub(1); 42759867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 42769867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 4277da8f07baf262972eb3e719fa07b073c180dff157Chris Forbes } 42789a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis for (auto event : cb_node->writeEventsBeforeWait) { 42799867daedbf52debc77d6568162ee21e071699b80Chris Forbes auto eventNode = dev_data->eventMap.find(event); 42809867daedbf52debc77d6568162ee21e071699b80Chris Forbes if (eventNode != dev_data->eventMap.end()) { 42819867daedbf52debc77d6568162ee21e071699b80Chris Forbes eventNode->second.write_in_use--; 42829867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 42839867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 42849a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis for (auto queryStatePair : cb_node->queryToStateMap) { 42859867daedbf52debc77d6568162ee21e071699b80Chris Forbes dev_data->queryToStateMap[queryStatePair.first] = queryStatePair.second; 42869867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 42879a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis for (auto eventStagePair : cb_node->eventToStageMap) { 42889867daedbf52debc77d6568162ee21e071699b80Chris Forbes dev_data->eventMap[eventStagePair.first].stageMask = eventStagePair.second; 4289da8f07baf262972eb3e719fa07b073c180dff157Chris Forbes } 42900a32ed7bdf03e7bda914e03c0bfa6ebf400cdf5bMichael Lentine 42919867daedbf52debc77d6568162ee21e071699b80Chris Forbes removeInFlightCmdBuffer(dev_data, cb); 42920a32ed7bdf03e7bda914e03c0bfa6ebf400cdf5bMichael Lentine } 42939867daedbf52debc77d6568162ee21e071699b80Chris Forbes 42949a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pFence = GetFenceNode(dev_data, submission.fence); 42959867daedbf52debc77d6568162ee21e071699b80Chris Forbes if (pFence) { 42969867daedbf52debc77d6568162ee21e071699b80Chris Forbes pFence->state = FENCE_RETIRED; 42970a32ed7bdf03e7bda914e03c0bfa6ebf400cdf5bMichael Lentine } 42989867daedbf52debc77d6568162ee21e071699b80Chris Forbes 42999867daedbf52debc77d6568162ee21e071699b80Chris Forbes pQueue->submissions.pop_front(); 43009867daedbf52debc77d6568162ee21e071699b80Chris Forbes pQueue->seq++; 4301b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine } 43029867daedbf52debc77d6568162ee21e071699b80Chris Forbes 43039867daedbf52debc77d6568162ee21e071699b80Chris Forbes // Roll other queues forward to the highest seq we saw a wait for 43049867daedbf52debc77d6568162ee21e071699b80Chris Forbes for (auto qs : otherQueueSeqs) { 43059a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis RetireWorkOnQueue(dev_data, GetQueueState(dev_data, qs.first), qs.second); 4306d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 43079867daedbf52debc77d6568162ee21e071699b80Chris Forbes} 4308651d92815dfff917308137bb67aacccc4f60df86Chris Forbes 4309651d92815dfff917308137bb67aacccc4f60df86Chris Forbes// Submit a fence to a queue, delimiting previous fences and previous untracked 4310651d92815dfff917308137bb67aacccc4f60df86Chris Forbes// work by it. 431136c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlisstatic void SubmitFence(QUEUE_STATE *pQueue, FENCE_NODE *pFence, uint64_t submitCount) { 4312cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes pFence->state = FENCE_INFLIGHT; 43139867daedbf52debc77d6568162ee21e071699b80Chris Forbes pFence->signaler.first = pQueue->queue; 43149867daedbf52debc77d6568162ee21e071699b80Chris Forbes pFence->signaler.second = pQueue->seq + pQueue->submissions.size() + submitCount; 4315b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine} 4316b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine 431751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourstatic bool validateCommandBufferSimultaneousUse(layer_data *dev_data, GLOBAL_CB_NODE *pCB, int current_submit_count) { 43185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool skip_call = false; 431951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if ((dev_data->globalInFlightCmdBuffers.count(pCB->commandBuffer) || current_submit_count > 1) && 43205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis !(pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT)) { 4321226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 4322f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen 0, __LINE__, VALIDATION_ERROR_00133, "DS", 4323f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen "Command Buffer 0x%p is already in use and is not marked for simultaneous use. %s", pCB->commandBuffer, 4324f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen validation_error_map[VALIDATION_ERROR_00133]); 43255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 43265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return skip_call; 43275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 43285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4329946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinskistatic bool validateCommandBufferState(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, const char *call_source, 4330440bdd357701497c3442e3515f12ac1cfffc180aTony Barbour int current_submit_count) { 4331c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis bool skip = false; 4332cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.command_buffer_state) return skip; 43330a59acde4b40fde3bbfea5811d2abf2c85ca62f4Tobin Ehlis // Validate ONE_TIME_SUBMIT_BIT CB is not being submitted more than once 4334946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if ((cb_state->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT) && 4335946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski (cb_state->submitCount + current_submit_count > 1)) { 4336c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, 4337c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis __LINE__, DRAWSTATE_COMMAND_BUFFER_SINGLE_SUBMIT_VIOLATION, "DS", 4338226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "Commandbuffer 0x%p was begun w/ VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT " 4339c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis "set, but has been submitted 0x%" PRIxLEAST64 " times.", 4340946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->commandBuffer, cb_state->submitCount + current_submit_count); 43410a59acde4b40fde3bbfea5811d2abf2c85ca62f4Tobin Ehlis } 43425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Validate that cmd buffers have been updated 4343946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (CB_RECORDED != cb_state->state) { 4344946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (CB_INVALID == cb_state->state) { 4345946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ReportInvalidCommandBuffer(dev_data, cb_state, call_source); 4346cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else { // Flag error for using CB w/o vkEndCommandBuffer() called 4347c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 4348946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski (uint64_t)(cb_state->commandBuffer), __LINE__, DRAWSTATE_NO_END_COMMAND_BUFFER, "DS", 4349946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "You must call vkEndCommandBuffer() on command buffer 0x%p before this call to %s!", 4350946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->commandBuffer, call_source); 43515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 43525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 4353c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis return skip; 43545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 43555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 435651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourstatic bool validateResources(layer_data *dev_data, GLOBAL_CB_NODE *cb_node) { 435751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour bool skip_call = false; 435851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 435951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour skip_call |= ValidateOrIncrementBoundObjects(dev_data, cb_node, false); 436051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour // TODO : We should be able to remove the NULL look-up checks from the code below as long as 436151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour // all the corresponding cases are verified to cause CB_INVALID state and the CB_INVALID state 436251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour // should then be flagged prior to calling this function 436351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour for (auto drawDataElement : cb_node->drawData) { 436451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour for (auto buffer : drawDataElement.buffers) { 436551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour auto buffer_state = GetBufferState(dev_data, buffer); 436651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (!buffer_state) { 436751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, 436851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour (uint64_t)(buffer), __LINE__, DRAWSTATE_INVALID_BUFFER, "DS", 436951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour "Cannot submit cmd buffer using deleted buffer 0x%" PRIx64 ".", (uint64_t)(buffer)); 437051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 437151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 437251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 437351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour return skip_call; 437451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour} 437551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 43767bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski// Validate that queueFamilyIndices of primary command buffers match this queue 43777bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski// Secondary command buffers were previously validated in vkCmdExecuteCommands(). 43787bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinskistatic bool validateQueueFamilyIndices(layer_data *dev_data, GLOBAL_CB_NODE *pCB, VkQueue queue) { 43797bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski bool skip_call = false; 43809a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pPool = GetCommandPoolNode(dev_data, pCB->createInfo.commandPool); 43819a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto queue_state = GetQueueState(dev_data, queue); 43827bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski 438336c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlis if (pPool && queue_state && (pPool->queueFamilyIndex != queue_state->queueFamilyIndex)) { 43847bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 4385f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen reinterpret_cast<uint64_t>(pCB->commandBuffer), __LINE__, VALIDATION_ERROR_00139, "DS", 4386f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen "vkQueueSubmit: Primary command buffer 0x%p created in queue family %d is being submitted on queue " 4387f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen "0x%p from queue family %d. %s", 4388f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen pCB->commandBuffer, pPool->queueFamilyIndex, queue, queue_state->queueFamilyIndex, 4389f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen validation_error_map[VALIDATION_ERROR_00139]); 43907bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski } 43917bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski 43927bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski return skip_call; 43937bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski} 43947bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski 439551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourstatic bool validatePrimaryCommandBufferState(layer_data *dev_data, GLOBAL_CB_NODE *pCB, int current_submit_count) { 43965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Track in-use for resources off of primary and any secondary CBs 439783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 4398a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes 4399a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes // If USAGE_SIMULTANEOUS_USE_BIT not set then CB cannot already be executing 4400a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes // on device 440151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour skip_call |= validateCommandBufferSimultaneousUse(dev_data, pCB, current_submit_count); 4402a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes 440351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour skip_call |= validateResources(dev_data, pCB); 4404a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes 44055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!pCB->secondaryCommandBuffers.empty()) { 44065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto secondaryCmdBuffer : pCB->secondaryCommandBuffers) { 44079a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pSubCB = GetCBNode(dev_data, secondaryCmdBuffer); 440851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour skip_call |= validateResources(dev_data, pSubCB); 44094c665b29a9d2906a378417546c7fc6436731d07fTobin Ehlis if ((pSubCB->primaryCommandBuffer != pCB->commandBuffer) && 44104c665b29a9d2906a378417546c7fc6436731d07fTobin Ehlis !(pSubCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT)) { 4411f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen log_msg( 4412f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, 4413f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen __LINE__, VALIDATION_ERROR_00135, "DS", 4414f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen "Commandbuffer 0x%p was submitted with secondary buffer 0x%p but that buffer has subsequently been bound to " 4415f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen "primary cmd buffer 0x%p and it does not have VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT set. %s", 4416f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen pCB->commandBuffer, secondaryCmdBuffer, pSubCB->primaryCommandBuffer, 4417f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen validation_error_map[VALIDATION_ERROR_00135]); 44185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 44195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 44205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 4421a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes 442251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour skip_call |= validateCommandBufferState(dev_data, pCB, "vkQueueSubmit()", current_submit_count); 4423a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes 442483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis return skip_call; 44255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 44265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4427bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic bool ValidateFenceForSubmit(layer_data *dev_data, FENCE_NODE *pFence) { 442883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 442981c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes 4430651d92815dfff917308137bb67aacccc4f60df86Chris Forbes if (pFence) { 4431cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes if (pFence->state == FENCE_INFLIGHT) { 4432f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen // TODO: opportunities for VALIDATION_ERROR_00127, VALIDATION_ERROR_01647, VALIDATION_ERROR_01953 443383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, 443483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis (uint64_t)(pFence->fence), __LINE__, DRAWSTATE_INVALID_FENCE, "DS", 443583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis "Fence 0x%" PRIx64 " is already in use by another submission.", (uint64_t)(pFence->fence)); 4436a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis } 443781c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes 4438cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes else if (pFence->state == FENCE_RETIRED) { 4439f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen // TODO: opportunities for VALIDATION_ERROR_00126, VALIDATION_ERROR_01646, VALIDATION_ERROR_01953 444083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= 444183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, 444283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis reinterpret_cast<uint64_t &>(pFence->fence), __LINE__, MEMTRACK_INVALID_FENCE_STATE, "MEM", 444383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis "Fence 0x%" PRIxLEAST64 " submitted in SIGNALED state. Fences must be reset before being submitted", 444483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis reinterpret_cast<uint64_t &>(pFence->fence)); 4445a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis } 44465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 444781c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes 444883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis return skip_call; 444981c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes} 445081c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes 445151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourstatic void PostCallRecordQueueSubmit(layer_data *dev_data, VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, 445251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour VkFence fence) { 44539a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pQueue = GetQueueState(dev_data, queue); 44549a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pFence = GetFenceNode(dev_data, fence); 4455d7d60cccc862fee2d0b3ad410c5fdcc40ddc83aeChris Forbes 4456651d92815dfff917308137bb67aacccc4f60df86Chris Forbes // Mark the fence in-use. 4457651d92815dfff917308137bb67aacccc4f60df86Chris Forbes if (pFence) { 44589867daedbf52debc77d6568162ee21e071699b80Chris Forbes SubmitFence(pQueue, pFence, std::max(1u, submitCount)); 4459651d92815dfff917308137bb67aacccc4f60df86Chris Forbes } 4460651d92815dfff917308137bb67aacccc4f60df86Chris Forbes 446151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour // Now process each individual submit 44625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) { 446351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour std::vector<VkCommandBuffer> cbs; 44645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkSubmitInfo *submit = &pSubmits[submit_idx]; 44659867daedbf52debc77d6568162ee21e071699b80Chris Forbes vector<SEMAPHORE_WAIT> semaphore_waits; 44669867daedbf52debc77d6568162ee21e071699b80Chris Forbes vector<VkSemaphore> semaphore_signals; 44675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < submit->waitSemaphoreCount; ++i) { 446851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour VkSemaphore semaphore = submit->pWaitSemaphores[i]; 446951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour auto pSemaphore = GetSemaphoreNode(dev_data, semaphore); 447051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (pSemaphore) { 447151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (pSemaphore->signaler.first != VK_NULL_HANDLE) { 447251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour semaphore_waits.push_back({semaphore, pSemaphore->signaler.first, pSemaphore->signaler.second}); 447351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pSemaphore->in_use.fetch_add(1); 447451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 447551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pSemaphore->signaler.first = VK_NULL_HANDLE; 447651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pSemaphore->signaled = false; 447751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 447851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 447951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour for (uint32_t i = 0; i < submit->signalSemaphoreCount; ++i) { 448051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour VkSemaphore semaphore = submit->pSignalSemaphores[i]; 448151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour auto pSemaphore = GetSemaphoreNode(dev_data, semaphore); 448251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (pSemaphore) { 448351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pSemaphore->signaler.first = queue; 448451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pSemaphore->signaler.second = pQueue->seq + pQueue->submissions.size() + 1; 448551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pSemaphore->signaled = true; 448651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pSemaphore->in_use.fetch_add(1); 448751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour semaphore_signals.push_back(semaphore); 448851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 448951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 449051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour for (uint32_t i = 0; i < submit->commandBufferCount; i++) { 449151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour auto cb_node = GetCBNode(dev_data, submit->pCommandBuffers[i]); 449251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (cb_node) { 449351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour cbs.push_back(submit->pCommandBuffers[i]); 449451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour for (auto secondaryCmdBuffer : cb_node->secondaryCommandBuffers) { 449551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour cbs.push_back(secondaryCmdBuffer); 449651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 449751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour UpdateCmdBufImageLayouts(dev_data, cb_node); 449851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour incrementResources(dev_data, cb_node); 449951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (!cb_node->secondaryCommandBuffers.empty()) { 450051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour for (auto secondaryCmdBuffer : cb_node->secondaryCommandBuffers) { 450151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour GLOBAL_CB_NODE *pSubCB = GetCBNode(dev_data, secondaryCmdBuffer); 450251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour incrementResources(dev_data, pSubCB); 450351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 450451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 450551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 450651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 450751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pQueue->submissions.emplace_back(cbs, semaphore_waits, semaphore_signals, 450851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour submit_idx == submitCount - 1 ? fence : VK_NULL_HANDLE); 450951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 451051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 451151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (pFence && !submitCount) { 451251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour // If no submissions, but just dropping a fence on the end of the queue, 451351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour // record an empty submission with just the fence, so we can determine 451451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour // its completion. 451551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pQueue->submissions.emplace_back(std::vector<VkCommandBuffer>(), std::vector<SEMAPHORE_WAIT>(), std::vector<VkSemaphore>(), 451651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour fence); 451751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 451851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour} 451951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 452051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourstatic bool PreCallValidateQueueSubmit(layer_data *dev_data, VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, 452151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour VkFence fence) { 452251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour auto pFence = GetFenceNode(dev_data, fence); 452351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour bool skip_call = ValidateFenceForSubmit(dev_data, pFence); 452451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (skip_call) { 452551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour return true; 452651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 452751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 452851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour unordered_set<VkSemaphore> signaled_semaphores; 452951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour unordered_set<VkSemaphore> unsignaled_semaphores; 453051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour vector<VkCommandBuffer> current_cmds; 453151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour unordered_map<ImageSubresourcePair, IMAGE_LAYOUT_NODE> localImageLayoutMap = dev_data->imageLayoutMap; 453251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour // Now verify each individual submit 453351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) { 453451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour const VkSubmitInfo *submit = &pSubmits[submit_idx]; 453551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour for (uint32_t i = 0; i < submit->waitSemaphoreCount; ++i) { 4536208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis skip_call |= ValidateStageMaskGsTsEnables(dev_data, submit->pWaitDstStageMask[i], "vkQueueSubmit()", 4537208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis VALIDATION_ERROR_00142, VALIDATION_ERROR_00143); 453801a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes VkSemaphore semaphore = submit->pWaitSemaphores[i]; 45399a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pSemaphore = GetSemaphoreNode(dev_data, semaphore); 454001a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes if (pSemaphore) { 454151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (unsignaled_semaphores.count(semaphore) || 4542440bdd357701497c3442e3515f12ac1cfffc180aTony Barbour (!(signaled_semaphores.count(semaphore)) && !(pSemaphore->signaled))) { 454383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= 45441344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT, 45451344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis reinterpret_cast<const uint64_t &>(semaphore), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS", 4546226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "Queue 0x%p is waiting on semaphore 0x%" PRIx64 " that has no way to be signaled.", queue, 4547226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis reinterpret_cast<const uint64_t &>(semaphore)); 454851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } else { 454951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour signaled_semaphores.erase(semaphore); 455051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour unsignaled_semaphores.insert(semaphore); 45511344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis } 45525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 45535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 45545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < submit->signalSemaphoreCount; ++i) { 455501a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes VkSemaphore semaphore = submit->pSignalSemaphores[i]; 45569a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pSemaphore = GetSemaphoreNode(dev_data, semaphore); 455701a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes if (pSemaphore) { 4558440bdd357701497c3442e3515f12ac1cfffc180aTony Barbour if (signaled_semaphores.count(semaphore) || (!(unsignaled_semaphores.count(semaphore)) && pSemaphore->signaled)) { 455983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= 45601344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT, 45611344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis reinterpret_cast<const uint64_t &>(semaphore), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS", 4562226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "Queue 0x%p is signaling semaphore 0x%" PRIx64 4563414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller " that has already been signaled but not waited on by queue 0x%" PRIx64 ".", 4564226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis queue, reinterpret_cast<const uint64_t &>(semaphore), 45659867daedbf52debc77d6568162ee21e071699b80Chris Forbes reinterpret_cast<uint64_t &>(pSemaphore->signaler.first)); 45661344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis } else { 456751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour unsignaled_semaphores.erase(semaphore); 456851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour signaled_semaphores.insert(semaphore); 45691344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis } 45700a32ed7bdf03e7bda914e03c0bfa6ebf400cdf5bMichael Lentine } 45715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 45725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < submit->commandBufferCount; i++) { 45739a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, submit->pCommandBuffers[i]); 457451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour skip_call |= ValidateCmdBufImageLayouts(dev_data, cb_node, localImageLayoutMap); 4575d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis if (cb_node) { 457651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour current_cmds.push_back(submit->pCommandBuffers[i]); 457751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour skip_call |= validatePrimaryCommandBufferState( 457851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour dev_data, cb_node, (int)std::count(current_cmds.begin(), current_cmds.end(), submit->pCommandBuffers[i])); 4579d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis skip_call |= validateQueueFamilyIndices(dev_data, cb_node, queue); 458051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 4581ea371fa7c8c57edb4d1436e4570cf54f3fc0463fTobin Ehlis // Potential early exit here as bad object state may crash in delayed function calls 458251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (skip_call) { 458351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour return true; 458451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 458551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 45861344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis // Call submit-time functions to validate/update state 4587d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis for (auto &function : cb_node->validate_functions) { 458883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= function(); 45891344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis } 4590d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis for (auto &function : cb_node->eventUpdates) { 459183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= function(queue); 45921344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis } 4593d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis for (auto &function : cb_node->queryUpdates) { 459483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= function(queue); 4595d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 45961344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis } 45975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 45989867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 459951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour return skip_call; 460051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour} 46019867daedbf52debc77d6568162ee21e071699b80Chris Forbes 460251920949f887ce8d3666c73c28ff19a5d8325a37Tony BarbourVKAPI_ATTR VkResult VKAPI_CALL QueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence) { 460351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map); 460451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour std::unique_lock<std::mutex> lock(global_lock); 460551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 460651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour bool skip = PreCallValidateQueueSubmit(dev_data, queue, submitCount, pSubmits, fence); 4607b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 46085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4609440bdd357701497c3442e3515f12ac1cfffc180aTony Barbour if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 461051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 461151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour VkResult result = dev_data->dispatch_table.QueueSubmit(queue, submitCount, pSubmits, fence); 461251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 461351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour lock.lock(); 461451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour PostCallRecordQueueSubmit(dev_data, queue, submitCount, pSubmits, fence); 461551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour lock.unlock(); 46165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 46175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 46185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4619f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultzstatic bool PreCallValidateAllocateMemory(layer_data *dev_data) { 4620f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz bool skip = false; 4621f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz if (dev_data->memObjMap.size() >= dev_data->phys_dev_properties.properties.limits.maxMemoryAllocationCount) { 4622f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 4623f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz reinterpret_cast<const uint64_t &>(dev_data->device), __LINE__, VALIDATION_ERROR_00611, "MEM", 4624f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz "Number of currently valid memory objects is not less than the maximum allowed (%u). %s", 4625f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz dev_data->phys_dev_properties.properties.limits.maxMemoryAllocationCount, 4626f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz validation_error_map[VALIDATION_ERROR_00611]); 4627f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz } 4628f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz return skip; 4629f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz} 4630f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz 4631f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultzstatic void PostCallRecordAllocateMemory(layer_data *dev_data, const VkMemoryAllocateInfo *pAllocateInfo, VkDeviceMemory *pMemory) { 4632f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz add_mem_obj_info(dev_data, dev_data->device, *pMemory, pAllocateInfo); 4633f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz return; 4634f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz} 4635f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz 463689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL AllocateMemory(VkDevice device, const VkMemoryAllocateInfo *pAllocateInfo, 463789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkDeviceMemory *pMemory) { 4638f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 463956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 4640f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz std::unique_lock<std::mutex> lock(global_lock); 4641f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz bool skip = PreCallValidateAllocateMemory(dev_data); 4642f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz if (!skip) { 4643f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz lock.unlock(); 4644f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz result = dev_data->dispatch_table.AllocateMemory(device, pAllocateInfo, pAllocator, pMemory); 4645f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz lock.lock(); 4646f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz if (VK_SUCCESS == result) { 4647f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz PostCallRecordAllocateMemory(dev_data, pAllocateInfo, pMemory); 4648f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz } 4649e12739a56d02ca2fb5f0273862668e7475a21a6cMark Lobodzinski } 46505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 46515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 46525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4653177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis// For given obj node, if it is use, flag a validation error and return callback result, else return false 4654177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlisbool ValidateObjectNotInUse(const layer_data *dev_data, BASE_NODE *obj_node, VK_OBJECT obj_struct, 4655177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis UNIQUE_VALIDATION_ERROR_CODE error_code) { 4656cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.object_in_use) return false; 4657177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis bool skip = false; 4658177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis if (obj_node->in_use.load()) { 4659177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, obj_struct.type, obj_struct.handle, __LINE__, 4660177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis error_code, "DS", "Cannot delete %s 0x%" PRIx64 " that is currently in use by a command buffer. %s", 4661177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis object_type_to_string(obj_struct.type), obj_struct.handle, validation_error_map[error_code]); 4662177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis } 4663177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis return skip; 4664177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis} 46655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4666177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlisstatic bool PreCallValidateFreeMemory(layer_data *dev_data, VkDeviceMemory mem, DEVICE_MEM_INFO **mem_info, VK_OBJECT *obj_struct) { 46679a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *mem_info = GetMemObjInfo(dev_data, mem); 466894165f5005d1fa37801d49067fe7751789b89d27Tobin Ehlis *obj_struct = {reinterpret_cast<uint64_t &>(mem), VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT}; 4669cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.free_memory) return false; 4670177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis bool skip = false; 4671177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis if (*mem_info) { 4672177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis skip |= ValidateObjectNotInUse(dev_data, *mem_info, *obj_struct, VALIDATION_ERROR_00620); 4673177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis } 4674177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis return skip; 4675177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis} 46765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4677177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlisstatic void PostCallRecordFreeMemory(layer_data *dev_data, VkDeviceMemory mem, DEVICE_MEM_INFO *mem_info, VK_OBJECT obj_struct) { 4678177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis // Clear mem binding for any bound objects 467947705d01140c9f1492885e6efc5fa262e7e1c6a0Tobin Ehlis for (auto obj : mem_info->obj_bindings) { 468047705d01140c9f1492885e6efc5fa262e7e1c6a0Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, obj.type, obj.handle, __LINE__, MEMTRACK_FREED_MEM_REF, 468147705d01140c9f1492885e6efc5fa262e7e1c6a0Tobin Ehlis "MEM", "VK Object 0x%" PRIxLEAST64 " still has a reference to mem obj 0x%" PRIxLEAST64, obj.handle, 468247705d01140c9f1492885e6efc5fa262e7e1c6a0Tobin Ehlis (uint64_t)mem_info->mem); 468347705d01140c9f1492885e6efc5fa262e7e1c6a0Tobin Ehlis switch (obj.type) { 4684cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT: { 46859a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_state = GetImageState(dev_data, reinterpret_cast<VkImage &>(obj.handle)); 4686cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski assert(image_state); // Any destroyed images should already be removed from bindings 4687cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski image_state->binding.mem = MEMORY_UNBOUND; 4688cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 4689cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 4690cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT: { 46919a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto buffer_state = GetBufferState(dev_data, reinterpret_cast<VkBuffer &>(obj.handle)); 4692cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski assert(buffer_state); // Any destroyed buffers should already be removed from bindings 4693cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski buffer_state->binding.mem = MEMORY_UNBOUND; 4694cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 4695cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 4696cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 4697cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Should only have buffer or image objects bound to memory 4698cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski assert(0); 4699177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis } 4700177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis } 4701177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis // Any bound cmd buffers are now invalid 470239c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis invalidateCommandBuffers(dev_data, mem_info->cb_bindings, obj_struct); 4703177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis dev_data->memObjMap.erase(mem); 4704177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis} 4705177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis 4706177063aac84fac6f4e650c2629a08b48be643f96Tobin EhlisVKAPI_ATTR void VKAPI_CALL FreeMemory(VkDevice device, VkDeviceMemory mem, const VkAllocationCallbacks *pAllocator) { 470756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 4708177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis DEVICE_MEM_INFO *mem_info = nullptr; 4709177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis VK_OBJECT obj_struct; 4710b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 4711177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis bool skip = PreCallValidateFreeMemory(dev_data, mem, &mem_info, &obj_struct); 4712177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis if (!skip) { 4713177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis lock.unlock(); 4714177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis dev_data->dispatch_table.FreeMemory(device, mem, pAllocator); 4715177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis lock.lock(); 4716405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (mem != VK_NULL_HANDLE) { 4717405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordFreeMemory(dev_data, mem, mem_info, obj_struct); 4718405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 471974243a735fe102b370237ddf80d3e6f7ec5246dbMark Mueller } 47205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 47215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4722f57fc64ac43691ad98e1713886b345465573070aTobin Ehlis// Validate that given Map memory range is valid. This means that the memory should not already be mapped, 4723f57fc64ac43691ad98e1713886b345465573070aTobin Ehlis// and that the size of the map range should be: 4724f57fc64ac43691ad98e1713886b345465573070aTobin Ehlis// 1. Not zero 4725f57fc64ac43691ad98e1713886b345465573070aTobin Ehlis// 2. Within the size of the memory allocation 472651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool ValidateMapMemRange(layer_data *dev_data, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size) { 472783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 47285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 47295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (size == 0) { 473051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 473183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis (uint64_t)mem, __LINE__, MEMTRACK_INVALID_MAP, "MEM", 473283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis "VkMapMemory: Attempting to map memory range of size zero"); 47335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 47345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 473551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis auto mem_element = dev_data->memObjMap.find(mem); 473651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (mem_element != dev_data->memObjMap.end()) { 473757fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis auto mem_info = mem_element->second.get(); 47385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // It is an application error to call VkMapMemory on an object that is already mapped 4739de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis if (mem_info->mem_range.size != 0) { 474051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 474183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis (uint64_t)mem, __LINE__, MEMTRACK_INVALID_MAP, "MEM", 474283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis "VkMapMemory: Attempting to map memory on an already-mapped object 0x%" PRIxLEAST64, (uint64_t)mem); 47435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 47445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 47455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Validate that offset + size is within object's allocationSize 47465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (size == VK_WHOLE_SIZE) { 4747de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis if (offset >= mem_info->alloc_info.allocationSize) { 474851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call = 474951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 475051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis (uint64_t)mem, __LINE__, MEMTRACK_INVALID_MAP, "MEM", 475151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis "Mapping Memory from 0x%" PRIx64 " to 0x%" PRIx64 475251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis " with size of VK_WHOLE_SIZE oversteps total array size 0x%" PRIx64, 475351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis offset, mem_info->alloc_info.allocationSize, mem_info->alloc_info.allocationSize); 47545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 47555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 4756de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis if ((offset + size) > mem_info->alloc_info.allocationSize) { 4757f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen skip_call = log_msg( 475851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 4759f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen (uint64_t)mem, __LINE__, VALIDATION_ERROR_00628, "MEM", 4760f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen "Mapping Memory from 0x%" PRIx64 " to 0x%" PRIx64 " oversteps total array size 0x%" PRIx64 ". %s", offset, 4761f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen size + offset, mem_info->alloc_info.allocationSize, validation_error_map[VALIDATION_ERROR_00628]); 47625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 47635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 47645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 476583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis return skip_call; 47665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 47675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 476851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic void storeMemRanges(layer_data *dev_data, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size) { 47699a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto mem_info = GetMemObjInfo(dev_data, mem); 477057fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis if (mem_info) { 4771de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis mem_info->mem_range.offset = offset; 4772de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis mem_info->mem_range.size = size; 47735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 47745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 47755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 477651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool deleteMemRanges(layer_data *dev_data, VkDeviceMemory mem) { 477783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 47789a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto mem_info = GetMemObjInfo(dev_data, mem); 477957fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis if (mem_info) { 4780de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis if (!mem_info->mem_range.size) { 47815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Valid Usage: memory must currently be mapped 478251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 4783f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen (uint64_t)mem, __LINE__, VALIDATION_ERROR_00649, "MEM", 4784f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen "Unmapping Memory without memory being mapped: mem obj 0x%" PRIxLEAST64 ". %s", (uint64_t)mem, 4785f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen validation_error_map[VALIDATION_ERROR_00649]); 47865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 4787de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis mem_info->mem_range.size = 0; 47885f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski if (mem_info->shadow_copy) { 47895f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski free(mem_info->shadow_copy_base); 47905f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski mem_info->shadow_copy_base = 0; 47915f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski mem_info->shadow_copy = 0; 47925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 47935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 479483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis return skip_call; 47955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 47965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 47975f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski// Guard value for pad data 47985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic char NoncoherentMemoryFillValue = 0xb; 47995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 48005f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinskistatic void initializeAndTrackMemory(layer_data *dev_data, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size, 48015f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski void **ppData) { 48029a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto mem_info = GetMemObjInfo(dev_data, mem); 480357fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis if (mem_info) { 4804de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis mem_info->p_driver_data = *ppData; 4805de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis uint32_t index = mem_info->alloc_info.memoryTypeIndex; 4806b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis if (dev_data->phys_dev_mem_props.memoryTypes[index].propertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) { 48075f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski mem_info->shadow_copy = 0; 48085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 48095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (size == VK_WHOLE_SIZE) { 48105f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski size = mem_info->alloc_info.allocationSize - offset; 48115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 48125f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski mem_info->shadow_pad_size = dev_data->phys_dev_properties.properties.limits.minMemoryMapAlignment; 48135f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski assert(vk_safe_modulo(mem_info->shadow_pad_size, 48145f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski dev_data->phys_dev_properties.properties.limits.minMemoryMapAlignment) == 0); 48155f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski // Ensure start of mapped region reflects hardware alignment constraints 48165f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski uint64_t map_alignment = dev_data->phys_dev_properties.properties.limits.minMemoryMapAlignment; 48175f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski 48185f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski // From spec: (ppData - offset) must be aligned to at least limits::minMemoryMapAlignment. 48195f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski uint64_t start_offset = offset % map_alignment; 48205f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski // Data passed to driver will be wrapped by a guardband of data to detect over- or under-writes. 4821bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski mem_info->shadow_copy_base = 4822bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski malloc(static_cast<size_t>(2 * mem_info->shadow_pad_size + size + map_alignment + start_offset)); 48235f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski 48245f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski mem_info->shadow_copy = 48255f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski reinterpret_cast<char *>((reinterpret_cast<uintptr_t>(mem_info->shadow_copy_base) + map_alignment) & 4826bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski ~(map_alignment - 1)) + 4827bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski start_offset; 48285f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski assert(vk_safe_modulo(reinterpret_cast<uintptr_t>(mem_info->shadow_copy) + mem_info->shadow_pad_size - start_offset, 48295f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski map_alignment) == 0); 48305f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski 48316e17c244b21ce43ac57404a00a0d844039eed363Mark Lobodzinski memset(mem_info->shadow_copy, NoncoherentMemoryFillValue, static_cast<size_t>(2 * mem_info->shadow_pad_size + size)); 48325f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski *ppData = static_cast<char *>(mem_info->shadow_copy) + mem_info->shadow_pad_size; 48335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 48345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 48355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 48365f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski 4837a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis// Verify that state for fence being waited on is appropriate. That is, 48389867daedbf52debc77d6568162ee21e071699b80Chris Forbes// a fence being waited on should not already be signaled and 4839a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis// it should have been submitted on a queue or during acquire next image 484049f6132af865afd5b7f413c91125971ac97c135aChris Forbesstatic inline bool verifyWaitFenceState(layer_data *dev_data, VkFence fence, const char *apiCall) { 484183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 48429b48b44dd917f95b5f34dd629ec4076fc87eb3a2Chris Forbes 48439a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pFence = GetFenceNode(dev_data, fence); 48449b48b44dd917f95b5f34dd629ec4076fc87eb3a2Chris Forbes if (pFence) { 4845cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes if (pFence->state == FENCE_UNSIGNALED) { 484683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, 484783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis reinterpret_cast<uint64_t &>(fence), __LINE__, MEMTRACK_INVALID_FENCE_STATE, "MEM", 4848cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s called for fence 0x%" PRIxLEAST64 4849cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " which has not been submitted on a Queue or during " 485083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis "acquire next image.", 485183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis apiCall, reinterpret_cast<uint64_t &>(fence)); 48525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 48535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 485483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis return skip_call; 48555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 4856a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis 4857b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlisstatic void RetireFence(layer_data *dev_data, VkFence fence) { 48589a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pFence = GetFenceNode(dev_data, fence); 4859b3ecd4c1fb44a2e65dfc13256afa9150aabde1d4Chris Forbes if (pFence->signaler.first != VK_NULL_HANDLE) { 486025002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Fence signaller is a queue -- use this as proof that prior operations on that queue have completed. 48619a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis RetireWorkOnQueue(dev_data, GetQueueState(dev_data, pFence->signaler.first), pFence->signaler.second); 4862bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski } else { 486325002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Fence signaller is the WSI. We're not tracking what the WSI op actually /was/ in CV yet, but we need to mark 486425002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // the fence as retired. 4865d4513979120463171eb479cdded9336eb9944da1Chris Forbes pFence->state = FENCE_RETIRED; 4866d4513979120463171eb479cdded9336eb9944da1Chris Forbes } 4867b3ecd4c1fb44a2e65dfc13256afa9150aabde1d4Chris Forbes} 4868b3ecd4c1fb44a2e65dfc13256afa9150aabde1d4Chris Forbes 4869accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlisstatic bool PreCallValidateWaitForFences(layer_data *dev_data, uint32_t fence_count, const VkFence *fences) { 4870cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.wait_for_fences) return false; 4871accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis bool skip = false; 4872accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis for (uint32_t i = 0; i < fence_count; i++) { 4873accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis skip |= verifyWaitFenceState(dev_data, fences[i], "vkWaitForFences"); 4874b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis skip |= VerifyQueueStateToFence(dev_data, fences[i]); 4875accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis } 4876accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis return skip; 4877accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis} 4878accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis 4879b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlisstatic void PostCallRecordWaitForFences(layer_data *dev_data, uint32_t fence_count, const VkFence *fences, VkBool32 wait_all) { 4880b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis // When we know that all fences are complete we can clean/remove their CBs 4881accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis if ((VK_TRUE == wait_all) || (1 == fence_count)) { 4882accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis for (uint32_t i = 0; i < fence_count; i++) { 4883b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis RetireFence(dev_data, fences[i]); 4884accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis } 4885accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis } 4886accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis // NOTE : Alternate case not handled here is when some fences have completed. In 4887accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis // this case for app to guarantee which fences completed it will have to call 4888b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis // vkGetFenceStatus() at which point we'll clean/remove their CBs if complete. 4889accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis} 4890accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis 4891bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL WaitForFences(VkDevice device, uint32_t fenceCount, const VkFence *pFences, VkBool32 waitAll, 4892bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski uint64_t timeout) { 489356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 48945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Verify fence status of submitted fences 4895b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 4896accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis bool skip = PreCallValidateWaitForFences(dev_data, fenceCount, pFences); 4897b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 4898cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 4899a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis 49004a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.WaitForFences(device, fenceCount, pFences, waitAll, timeout); 4901414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller 49025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (result == VK_SUCCESS) { 4903b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.lock(); 4904b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis PostCallRecordWaitForFences(dev_data, fenceCount, pFences, waitAll); 4905b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 49065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 49075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 49085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 49095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4910f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlisstatic bool PreCallValidateGetFenceStatus(layer_data *dev_data, VkFence fence) { 4911cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.get_fence_state) return false; 4912f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis return verifyWaitFenceState(dev_data, fence, "vkGetFenceStatus"); 4913f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis} 4914f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis 4915b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlisstatic void PostCallRecordGetFenceStatus(layer_data *dev_data, VkFence fence) { RetireFence(dev_data, fence); } 4916f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis 491789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL GetFenceStatus(VkDevice device, VkFence fence) { 491856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 4919b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 4920f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis bool skip = PreCallValidateGetFenceStatus(dev_data, fence); 4921b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 4922cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 4923a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis 49244a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.GetFenceStatus(device, fence); 49255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (result == VK_SUCCESS) { 4926f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis lock.lock(); 4927b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis PostCallRecordGetFenceStatus(dev_data, fence); 4928f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis lock.unlock(); 49295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 49305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 49315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 49325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 49333b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlisstatic void PostCallRecordGetDeviceQueue(layer_data *dev_data, uint32_t q_family_index, VkQueue queue) { 49343b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis // Add queue to tracking set only if it is new 49353b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis auto result = dev_data->queues.emplace(queue); 49363b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis if (result.second == true) { 493736c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlis QUEUE_STATE *queue_state = &dev_data->queueMap[queue]; 49383b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis queue_state->queue = queue; 49393b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis queue_state->queueFamilyIndex = q_family_index; 49403b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis queue_state->seq = 0; 49413b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis } 49423b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis} 49433b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis 4944bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL GetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue *pQueue) { 494556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 49464a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue); 4947b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 4948b376edacad6f7ab3fcc0a914e9b1673a9fcd5143Mark Lobodzinski 49493b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis PostCallRecordGetDeviceQueue(dev_data, queueFamilyIndex, *pQueue); 49505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 49515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 495236c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlisstatic bool PreCallValidateQueueWaitIdle(layer_data *dev_data, VkQueue queue, QUEUE_STATE **queue_state) { 49539a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *queue_state = GetQueueState(dev_data, queue); 4954cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.queue_wait_idle) return false; 4955e0cec9ec6dd3cfd83345cabba55ec021681801dbTobin Ehlis return VerifyQueueStateToSeq(dev_data, *queue_state, (*queue_state)->seq + (*queue_state)->submissions.size()); 49564273a1c157585a645dca4c960086032793899d05Tobin Ehlis} 49574273a1c157585a645dca4c960086032793899d05Tobin Ehlis 495836c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlisstatic void PostCallRecordQueueWaitIdle(layer_data *dev_data, QUEUE_STATE *queue_state) { 4959e0cec9ec6dd3cfd83345cabba55ec021681801dbTobin Ehlis RetireWorkOnQueue(dev_data, queue_state, queue_state->seq + queue_state->submissions.size()); 49604273a1c157585a645dca4c960086032793899d05Tobin Ehlis} 49614273a1c157585a645dca4c960086032793899d05Tobin Ehlis 496289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL QueueWaitIdle(VkQueue queue) { 496356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map); 496436c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlis QUEUE_STATE *queue_state = nullptr; 49659867daedbf52debc77d6568162ee21e071699b80Chris Forbes std::unique_lock<std::mutex> lock(global_lock); 49664273a1c157585a645dca4c960086032793899d05Tobin Ehlis bool skip = PreCallValidateQueueWaitIdle(dev_data, queue, &queue_state); 49679867daedbf52debc77d6568162ee21e071699b80Chris Forbes lock.unlock(); 4968cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 49694a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.QueueWaitIdle(queue); 49704273a1c157585a645dca4c960086032793899d05Tobin Ehlis if (VK_SUCCESS == result) { 4971e0cec9ec6dd3cfd83345cabba55ec021681801dbTobin Ehlis lock.lock(); 4972e0cec9ec6dd3cfd83345cabba55ec021681801dbTobin Ehlis PostCallRecordQueueWaitIdle(dev_data, queue_state); 4973e0cec9ec6dd3cfd83345cabba55ec021681801dbTobin Ehlis lock.unlock(); 49744273a1c157585a645dca4c960086032793899d05Tobin Ehlis } 49755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 49765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 49775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 49788767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlisstatic bool PreCallValidateDeviceWaitIdle(layer_data *dev_data) { 4979cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.device_wait_idle) return false; 49808767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis bool skip = false; 49818767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis for (auto &queue : dev_data->queueMap) { 49828767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis skip |= VerifyQueueStateToSeq(dev_data, &queue.second, queue.second.seq + queue.second.submissions.size()); 49838767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis } 49848767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis return skip; 49858767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis} 49868767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis 49878767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlisstatic void PostCallRecordDeviceWaitIdle(layer_data *dev_data) { 49888767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis for (auto &queue : dev_data->queueMap) { 49898767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis RetireWorkOnQueue(dev_data, &queue.second, queue.second.seq + queue.second.submissions.size()); 49908767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis } 49918767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis} 49928767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis 499389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL DeviceWaitIdle(VkDevice device) { 499456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 4995b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 49968767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis bool skip = PreCallValidateDeviceWaitIdle(dev_data); 4997b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 4998cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 49994a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.DeviceWaitIdle(device); 50008767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis if (VK_SUCCESS == result) { 50018767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis lock.lock(); 50028767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis PostCallRecordDeviceWaitIdle(dev_data); 50038767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis lock.unlock(); 50048767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis } 50055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 50065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 50075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 50081d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlisstatic bool PreCallValidateDestroyFence(layer_data *dev_data, VkFence fence, FENCE_NODE **fence_node, VK_OBJECT *obj_struct) { 50099a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *fence_node = GetFenceNode(dev_data, fence); 50101d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis *obj_struct = {reinterpret_cast<uint64_t &>(fence), VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT}; 5011cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_fence) return false; 50121d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis bool skip = false; 50131d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis if (*fence_node) { 50141d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis if ((*fence_node)->state == FENCE_INFLIGHT) { 50151d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, 5016208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis (uint64_t)(fence), __LINE__, VALIDATION_ERROR_00173, "DS", "Fence 0x%" PRIx64 " is in use. %s", 5017208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis (uint64_t)(fence), validation_error_map[VALIDATION_ERROR_00173]); 50181d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis } 50191d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis } 50201d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis return skip; 50211d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis} 50221d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis 50231d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlisstatic void PostCallRecordDestroyFence(layer_data *dev_data, VkFence fence) { dev_data->fenceMap.erase(fence); } 50241d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis 502589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL DestroyFence(VkDevice device, VkFence fence, const VkAllocationCallbacks *pAllocator) { 502656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 50271d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis // Common data objects used pre & post call 50281d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis FENCE_NODE *fence_node = nullptr; 50291d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis VK_OBJECT obj_struct; 5030b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 50311d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis bool skip = PreCallValidateDestroyFence(dev_data, fence, &fence_node, &obj_struct); 50321344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis 50331d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis if (!skip) { 50341d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis lock.unlock(); 50354a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyFence(device, fence, pAllocator); 50361d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis lock.lock(); 50371d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis PostCallRecordDestroyFence(dev_data, fence); 50381d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis } 50395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 50405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5041c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlisstatic bool PreCallValidateDestroySemaphore(layer_data *dev_data, VkSemaphore semaphore, SEMAPHORE_NODE **sema_node, 5042c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis VK_OBJECT *obj_struct) { 50439a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *sema_node = GetSemaphoreNode(dev_data, semaphore); 5044c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis *obj_struct = {reinterpret_cast<uint64_t &>(semaphore), VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT}; 5045cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_semaphore) return false; 5046c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis bool skip = false; 5047c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis if (*sema_node) { 5048c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis skip |= ValidateObjectNotInUse(dev_data, *sema_node, *obj_struct, VALIDATION_ERROR_00199); 5049c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis } 5050c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis return skip; 5051c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis} 5052c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis 5053c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlisstatic void PostCallRecordDestroySemaphore(layer_data *dev_data, VkSemaphore sema) { dev_data->semaphoreMap.erase(sema); } 5054c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis 5055bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroySemaphore(VkDevice device, VkSemaphore semaphore, const VkAllocationCallbacks *pAllocator) { 505656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 5057c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis SEMAPHORE_NODE *sema_node; 5058c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis VK_OBJECT obj_struct; 5059e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 5060c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis bool skip = PreCallValidateDestroySemaphore(dev_data, semaphore, &sema_node, &obj_struct); 5061eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis if (!skip) { 5062eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis lock.unlock(); 50634a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroySemaphore(device, semaphore, pAllocator); 5064c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis lock.lock(); 5065c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis PostCallRecordDestroySemaphore(dev_data, semaphore); 506699d938c90c2f000ee73fb13513dacf84ffa5651fMark Mueller } 50675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 50685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 50694710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlisstatic bool PreCallValidateDestroyEvent(layer_data *dev_data, VkEvent event, EVENT_STATE **event_state, VK_OBJECT *obj_struct) { 50709a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *event_state = GetEventNode(dev_data, event); 507194165f5005d1fa37801d49067fe7751789b89d27Tobin Ehlis *obj_struct = {reinterpret_cast<uint64_t &>(event), VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT}; 5072cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_event) return false; 5073d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis bool skip = false; 5074d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis if (*event_state) { 5075d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis skip |= ValidateObjectNotInUse(dev_data, *event_state, *obj_struct, VALIDATION_ERROR_00213); 5076d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis } 5077d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis return skip; 5078d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis} 5079d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis 50804710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlisstatic void PostCallRecordDestroyEvent(layer_data *dev_data, VkEvent event, EVENT_STATE *event_state, VK_OBJECT obj_struct) { 508139c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis invalidateCommandBuffers(dev_data, event_state->cb_bindings, obj_struct); 5082d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis dev_data->eventMap.erase(event); 5083d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis} 5084d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis 508589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL DestroyEvent(VkDevice device, VkEvent event, const VkAllocationCallbacks *pAllocator) { 508656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 50874710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis EVENT_STATE *event_state = nullptr; 5088d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis VK_OBJECT obj_struct; 5089b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 5090d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis bool skip = PreCallValidateDestroyEvent(dev_data, event, &event_state, &obj_struct); 5091f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis if (!skip) { 5092f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis lock.unlock(); 50934a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyEvent(device, event, pAllocator); 5094d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis lock.lock(); 5095405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (event != VK_NULL_HANDLE) { 5096405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyEvent(dev_data, event, event_state, obj_struct); 5097405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 5098f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis } 50995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 51005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 510183c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlisstatic bool PreCallValidateDestroyQueryPool(layer_data *dev_data, VkQueryPool query_pool, QUERY_POOL_NODE **qp_state, 510283c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis VK_OBJECT *obj_struct) { 51039a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *qp_state = GetQueryPoolNode(dev_data, query_pool); 510483c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis *obj_struct = {reinterpret_cast<uint64_t &>(query_pool), VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT}; 5105cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_query_pool) return false; 510683c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis bool skip = false; 510783c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis if (*qp_state) { 510883c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis skip |= ValidateObjectNotInUse(dev_data, *qp_state, *obj_struct, VALIDATION_ERROR_01012); 510983c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis } 511083c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis return skip; 511183c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis} 511283c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis 5113bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic void PostCallRecordDestroyQueryPool(layer_data *dev_data, VkQueryPool query_pool, QUERY_POOL_NODE *qp_state, 5114bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VK_OBJECT obj_struct) { 511583c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis invalidateCommandBuffers(dev_data, qp_state->cb_bindings, obj_struct); 511683c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis dev_data->queryPoolMap.erase(query_pool); 511783c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis} 511883c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis 5119bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyQueryPool(VkDevice device, VkQueryPool queryPool, const VkAllocationCallbacks *pAllocator) { 512056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 512183c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis QUERY_POOL_NODE *qp_state = nullptr; 512283c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis VK_OBJECT obj_struct; 5123ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 512483c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis bool skip = PreCallValidateDestroyQueryPool(dev_data, queryPool, &qp_state, &obj_struct); 5125f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis if (!skip) { 5126f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis lock.unlock(); 51274a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyQueryPool(device, queryPool, pAllocator); 512883c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis lock.lock(); 5129405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (queryPool != VK_NULL_HANDLE) { 5130405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyQueryPool(dev_data, queryPool, qp_state, obj_struct); 5131405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 5132f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis } 51335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 51349fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlisstatic bool PreCallValidateGetQueryPoolResults(layer_data *dev_data, VkQueryPool query_pool, uint32_t first_query, 51359fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis uint32_t query_count, VkQueryResultFlags flags, 51369fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis unordered_map<QueryObject, vector<VkCommandBuffer>> *queries_in_flight) { 51379fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis for (auto cmd_buffer : dev_data->globalInFlightCmdBuffers) { 51389a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb = GetCBNode(dev_data, cmd_buffer); 51399fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis for (auto query_state_pair : cb->queryToStateMap) { 51409fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis (*queries_in_flight)[query_state_pair.first].push_back(cmd_buffer); 51415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 51425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5143cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.get_query_pool_results) return false; 51449fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis bool skip = false; 51459fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis for (uint32_t i = 0; i < query_count; ++i) { 51469fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis QueryObject query = {query_pool, first_query + i}; 51479fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis auto qif_pair = queries_in_flight->find(query); 51489fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis auto query_state_pair = dev_data->queryToStateMap.find(query); 51499fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis if (query_state_pair != dev_data->queryToStateMap.end()) { 5150ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski // Available and in flight 51519fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis if (qif_pair != queries_in_flight->end() && query_state_pair != dev_data->queryToStateMap.end() && 51529fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis query_state_pair->second) { 51539fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis for (auto cmd_buffer : qif_pair->second) { 51549a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb = GetCBNode(dev_data, cmd_buffer); 51559fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis auto query_event_pair = cb->waitedEventsBeforeQueryReset.find(query); 51569fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis if (query_event_pair == cb->waitedEventsBeforeQueryReset.end()) { 51579fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 51589fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, __LINE__, DRAWSTATE_INVALID_QUERY, "DS", 51599fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis "Cannot get query results on queryPool 0x%" PRIx64 " with index %d which is in flight.", 51609fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis (uint64_t)(query_pool), first_query + i); 5161ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski } 5162ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski } 5163ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski // Unavailable and in flight 51649fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis } else if (qif_pair != queries_in_flight->end() && query_state_pair != dev_data->queryToStateMap.end() && 51659fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis !query_state_pair->second) { 5166ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski // TODO : Can there be the same query in use by multiple command buffers in flight? 5167ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski bool make_available = false; 51689fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis for (auto cmd_buffer : qif_pair->second) { 51699a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb = GetCBNode(dev_data, cmd_buffer); 51709fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis make_available |= cb->queryToStateMap[query]; 5171ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski } 5172ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski if (!(((flags & VK_QUERY_RESULT_PARTIAL_BIT) || (flags & VK_QUERY_RESULT_WAIT_BIT)) && make_available)) { 51739fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 51749fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, __LINE__, DRAWSTATE_INVALID_QUERY, "DS", 51759fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis "Cannot get query results on queryPool 0x%" PRIx64 " with index %d which is unavailable.", 51769fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis (uint64_t)(query_pool), first_query + i); 51775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5178ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski // Unavailable 51799fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis } else if (query_state_pair != dev_data->queryToStateMap.end() && !query_state_pair->second) { 51809fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, 51819fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis __LINE__, DRAWSTATE_INVALID_QUERY, "DS", 51829fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis "Cannot get query results on queryPool 0x%" PRIx64 " with index %d which is unavailable.", 51839fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis (uint64_t)(query_pool), first_query + i); 51849fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis // Uninitialized 51859fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis } else if (query_state_pair == dev_data->queryToStateMap.end()) { 51869fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, 51879fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis __LINE__, DRAWSTATE_INVALID_QUERY, "DS", 51889fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis "Cannot get query results on queryPool 0x%" PRIx64 51899fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis " with index %d as data has not been collected for this index.", 51909fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis (uint64_t)(query_pool), first_query + i); 51915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 51925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 51935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 51949fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis return skip; 51959fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis} 51969fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis 51979fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlisstatic void PostCallRecordGetQueryPoolResults(layer_data *dev_data, VkQueryPool query_pool, uint32_t first_query, 51989fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis uint32_t query_count, 51999fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis unordered_map<QueryObject, vector<VkCommandBuffer>> *queries_in_flight) { 52009fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis for (uint32_t i = 0; i < query_count; ++i) { 52019fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis QueryObject query = {query_pool, first_query + i}; 52029fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis auto qif_pair = queries_in_flight->find(query); 52039fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis auto query_state_pair = dev_data->queryToStateMap.find(query); 52049fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis if (query_state_pair != dev_data->queryToStateMap.end()) { 52059fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis // Available and in flight 52069fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis if (qif_pair != queries_in_flight->end() && query_state_pair != dev_data->queryToStateMap.end() && 52079fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis query_state_pair->second) { 52089fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis for (auto cmd_buffer : qif_pair->second) { 52099a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb = GetCBNode(dev_data, cmd_buffer); 52109fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis auto query_event_pair = cb->waitedEventsBeforeQueryReset.find(query); 52119fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis if (query_event_pair != cb->waitedEventsBeforeQueryReset.end()) { 52129fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis for (auto event : query_event_pair->second) { 52139fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis dev_data->eventMap[event].needsSignaled = true; 52149fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis } 52159fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis } 52169fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis } 52179fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis } 52189fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis } 52199fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis } 52209fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis} 52219fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis 52229fdee42cd357379efb9aa27f90beb75d1f824955Tobin EhlisVKAPI_ATTR VkResult VKAPI_CALL GetQueryPoolResults(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, 52239fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis size_t dataSize, void *pData, VkDeviceSize stride, VkQueryResultFlags flags) { 522456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 52259fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis unordered_map<QueryObject, vector<VkCommandBuffer>> queries_in_flight; 52269fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 52279fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis bool skip = PreCallValidateGetQueryPoolResults(dev_data, queryPool, firstQuery, queryCount, flags, &queries_in_flight); 5228b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 5229cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 52309fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis VkResult result = 52319fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis dev_data->dispatch_table.GetQueryPoolResults(device, queryPool, firstQuery, queryCount, dataSize, pData, stride, flags); 52329fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis lock.lock(); 52339fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis PostCallRecordGetQueryPoolResults(dev_data, queryPool, firstQuery, queryCount, &queries_in_flight); 52349fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis lock.unlock(); 52359fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis return result; 52365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 52375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5238825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Return true if given ranges intersect, else false 5239825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Prereq : For both ranges, range->end - range->start > 0. This case should have already resulted 5240825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// in an error so not checking that here 5241825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// pad_ranges bool indicates a linear and non-linear comparison which requires padding 5242825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// In the case where padding is required, if an alias is encountered then a validation error is reported and skip_call 5243825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// may be set by the callback function so caller should merge in skip_call value if padding case is possible. 52447dc3fbb89e2dcf3df8fc2e6639a867a959fef3f3Tobin Ehlisstatic bool rangesIntersect(layer_data const *dev_data, MEMORY_RANGE const *range1, MEMORY_RANGE const *range2, bool *skip_call) { 52457dc3fbb89e2dcf3df8fc2e6639a867a959fef3f3Tobin Ehlis *skip_call = false; 5246825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis auto r1_start = range1->start; 5247825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis auto r1_end = range1->end; 5248825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis auto r2_start = range2->start; 5249825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis auto r2_end = range2->end; 5250825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis VkDeviceSize pad_align = 1; 5251825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis if (range1->linear != range2->linear) { 5252825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis pad_align = dev_data->phys_dev_properties.properties.limits.bufferImageGranularity; 5253825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis } 5254cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if ((r1_end & ~(pad_align - 1)) < (r2_start & ~(pad_align - 1))) return false; 5255cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if ((r1_start & ~(pad_align - 1)) > (r2_end & ~(pad_align - 1))) return false; 525647aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski 5257825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis if (range1->linear != range2->linear) { 525853ecec26e80e4d18b57d24ed6eb91a3c9da4b95cTobin Ehlis // In linear vs. non-linear case, warn of aliasing 5259825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis const char *r1_linear_str = range1->linear ? "Linear" : "Non-linear"; 5260825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis const char *r1_type_str = range1->image ? "image" : "buffer"; 5261825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis const char *r2_linear_str = range2->linear ? "linear" : "non-linear"; 5262825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis const char *r2_type_str = range2->image ? "image" : "buffer"; 5263825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis auto obj_type = range1->image ? VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT : VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT; 526453ecec26e80e4d18b57d24ed6eb91a3c9da4b95cTobin Ehlis *skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, obj_type, range1->handle, 0, 526553ecec26e80e4d18b57d24ed6eb91a3c9da4b95cTobin Ehlis MEMTRACK_INVALID_ALIASING, "MEM", "%s %s 0x%" PRIx64 " is aliased with %s %s 0x%" PRIx64 526653ecec26e80e4d18b57d24ed6eb91a3c9da4b95cTobin Ehlis " which may indicate a bug. For further info refer to the " 526753ecec26e80e4d18b57d24ed6eb91a3c9da4b95cTobin Ehlis "Buffer-Image Granularity section of the Vulkan specification. " 526853ecec26e80e4d18b57d24ed6eb91a3c9da4b95cTobin Ehlis "(https://www.khronos.org/registry/vulkan/specs/1.0-extensions/" 526953ecec26e80e4d18b57d24ed6eb91a3c9da4b95cTobin Ehlis "xhtml/vkspec.html#resources-bufferimagegranularity)", 527053ecec26e80e4d18b57d24ed6eb91a3c9da4b95cTobin Ehlis r1_linear_str, r1_type_str, range1->handle, r2_linear_str, r2_type_str, range2->handle); 527147aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski } 5272825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis // Ranges intersect 5273825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis return true; 527447aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski} 5275623548a271287ae55415e45e3c654ee66d4e79ffTobin Ehlis// Simplified rangesIntersect that calls above function to check range1 for intersection with offset & end addresses 5276c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinskibool rangesIntersect(layer_data const *dev_data, MEMORY_RANGE const *range1, VkDeviceSize offset, VkDeviceSize end) { 5277825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis // Create a local MEMORY_RANGE struct to wrap offset/size 5278825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis MEMORY_RANGE range_wrap; 5279825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis // Synch linear with range1 to avoid padding and potential validation error case 5280825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis range_wrap.linear = range1->linear; 5281825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis range_wrap.start = offset; 5282cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis range_wrap.end = end; 5283825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis bool tmp_bool; 52847dc3fbb89e2dcf3df8fc2e6639a867a959fef3f3Tobin Ehlis return rangesIntersect(dev_data, range1, &range_wrap, &tmp_bool); 5285825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis} 5286cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis// For given mem_info, set all ranges valid that intersect [offset-end] range 5287cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis// TODO : For ranges where there is no alias, we may want to create new buffer ranges that are valid 5288cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlisstatic void SetMemRangesValid(layer_data const *dev_data, DEVICE_MEM_INFO *mem_info, VkDeviceSize offset, VkDeviceSize end) { 5289cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis bool tmp_bool = false; 5290f6e16b28b808a342cb92768001afa2cfeee08a11Tobin Ehlis MEMORY_RANGE map_range = {}; 5291cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis map_range.linear = true; 5292cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis map_range.start = offset; 5293cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis map_range.end = end; 5294cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis for (auto &handle_range_pair : mem_info->bound_ranges) { 52957dc3fbb89e2dcf3df8fc2e6639a867a959fef3f3Tobin Ehlis if (rangesIntersect(dev_data, &handle_range_pair.second, &map_range, &tmp_bool)) { 5296cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis // TODO : WARN here if tmp_bool true? 5297cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis handle_range_pair.second.valid = true; 5298cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis } 5299cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis } 5300cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis} 5301825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Object with given handle is being bound to memory w/ given mem_info struct. 5302825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Track the newly bound memory range with given memoryOffset 5303825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Also scan any previous ranges, track aliased ranges with new range, and flag an error if a linear 5304825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// and non-linear range incorrectly overlap. 5305825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Return true if an error is flagged and the user callback returns "true", otherwise false 5306825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// is_image indicates an image object, otherwise handle is for a buffer 5307825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// is_linear indicates a buffer or linear image 53087992c34b28dd617787f0e4d34fd023f894495edbCort Stratton// api_name API entry point that triggered this call 5309825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlisstatic bool InsertMemoryRange(layer_data const *dev_data, uint64_t handle, DEVICE_MEM_INFO *mem_info, VkDeviceSize memoryOffset, 53107992c34b28dd617787f0e4d34fd023f894495edbCort Stratton VkMemoryRequirements memRequirements, bool is_image, bool is_linear, const char *api_name) { 5311825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis bool skip_call = false; 53125360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis MEMORY_RANGE range; 5313825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis 53147992c34b28dd617787f0e4d34fd023f894495edbCort Stratton if (memoryOffset >= mem_info->alloc_info.allocationSize) { 53157992c34b28dd617787f0e4d34fd023f894495edbCort Stratton UNIQUE_VALIDATION_ERROR_CODE error_code = is_image ? VALIDATION_ERROR_00805 : VALIDATION_ERROR_00793; 53167992c34b28dd617787f0e4d34fd023f894495edbCort Stratton skip_call = 53177992c34b28dd617787f0e4d34fd023f894495edbCort Stratton log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 53187992c34b28dd617787f0e4d34fd023f894495edbCort Stratton reinterpret_cast<uint64_t &>(mem_info->mem), __LINE__, error_code, "MEM", 53197992c34b28dd617787f0e4d34fd023f894495edbCort Stratton "In %s, attempting to bind memory (0x%" PRIxLEAST64 ") to object (0x%" PRIxLEAST64 53207992c34b28dd617787f0e4d34fd023f894495edbCort Stratton "), memoryOffset=0x%" PRIxLEAST64 " must be less than the memory allocation size 0x%" PRIxLEAST64 ". %s", 53217992c34b28dd617787f0e4d34fd023f894495edbCort Stratton api_name, reinterpret_cast<uint64_t &>(mem_info->mem), handle, memoryOffset, 53227992c34b28dd617787f0e4d34fd023f894495edbCort Stratton mem_info->alloc_info.allocationSize, validation_error_map[error_code]); 53237992c34b28dd617787f0e4d34fd023f894495edbCort Stratton } 53247992c34b28dd617787f0e4d34fd023f894495edbCort Stratton 5325825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis range.image = is_image; 532647aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski range.handle = handle; 5327825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis range.linear = is_linear; 5328f541bf53dee6daf82a4c8304354eac599a884d29Tobin Ehlis range.valid = mem_info->global_valid; 5329825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis range.memory = mem_info->mem; 533047aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski range.start = memoryOffset; 5331825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis range.size = memRequirements.size; 533247aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski range.end = memoryOffset + memRequirements.size - 1; 53335360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis range.aliases.clear(); 53345360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis // Update Memory aliasing 533575f4c8cec0996021a4258b9bf920a9e0fea4eac1Tobin 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 53365360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis // inserted into map before loop to get the final ptr, then we may enter loop when not needed & we check range against itself 53375360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis std::unordered_set<MEMORY_RANGE *> tmp_alias_ranges; 5338825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis for (auto &obj_range_pair : mem_info->bound_ranges) { 5339825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis auto check_range = &obj_range_pair.second; 53405360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis bool intersection_error = false; 53417dc3fbb89e2dcf3df8fc2e6639a867a959fef3f3Tobin Ehlis if (rangesIntersect(dev_data, &range, check_range, &intersection_error)) { 5342825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis skip_call |= intersection_error; 5343825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis range.aliases.insert(check_range); 53445360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis tmp_alias_ranges.insert(check_range); 5345825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis } 5346825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis } 53475360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis mem_info->bound_ranges[handle] = std::move(range); 53485360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis for (auto tmp_range : tmp_alias_ranges) { 53495360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis tmp_range->aliases.insert(&mem_info->bound_ranges[handle]); 53505360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis } 5351825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis if (is_image) 5352825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis mem_info->bound_images.insert(handle); 5353825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis else 5354825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis mem_info->bound_buffers.insert(handle); 5355825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis 5356825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis return skip_call; 535747aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski} 535847aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski 53599f12a235bb9c014878a98ce385b68587add2538aTobin Ehlisstatic bool InsertImageMemoryRange(layer_data const *dev_data, VkImage image, DEVICE_MEM_INFO *mem_info, VkDeviceSize mem_offset, 53607992c34b28dd617787f0e4d34fd023f894495edbCort Stratton VkMemoryRequirements mem_reqs, bool is_linear, const char *api_name) { 53617992c34b28dd617787f0e4d34fd023f894495edbCort Stratton return InsertMemoryRange(dev_data, reinterpret_cast<uint64_t &>(image), mem_info, mem_offset, mem_reqs, true, is_linear, 53627992c34b28dd617787f0e4d34fd023f894495edbCort Stratton api_name); 5363825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis} 5364825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis 53659f12a235bb9c014878a98ce385b68587add2538aTobin Ehlisstatic bool InsertBufferMemoryRange(layer_data const *dev_data, VkBuffer buffer, DEVICE_MEM_INFO *mem_info, VkDeviceSize mem_offset, 53667992c34b28dd617787f0e4d34fd023f894495edbCort Stratton VkMemoryRequirements mem_reqs, const char *api_name) { 53677992c34b28dd617787f0e4d34fd023f894495edbCort Stratton return InsertMemoryRange(dev_data, reinterpret_cast<uint64_t &>(buffer), mem_info, mem_offset, mem_reqs, false, true, api_name); 5368825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis} 5369825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis 5370825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Remove MEMORY_RANGE struct for give handle from bound_ranges of mem_info 5371825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// is_image indicates if handle is for image or buffer 5372825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// This function will also remove the handle-to-index mapping from the appropriate 5373825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// map and clean up any aliases for range being removed. 5374825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlisstatic void RemoveMemoryRange(uint64_t handle, DEVICE_MEM_INFO *mem_info, bool is_image) { 5375825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis auto erase_range = &mem_info->bound_ranges[handle]; 5376825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis for (auto alias_range : erase_range->aliases) { 5377825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis alias_range->aliases.erase(erase_range); 537847aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski } 53795360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis erase_range->aliases.clear(); 5380825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis mem_info->bound_ranges.erase(handle); 53811cba4e1b5940c6818572e05dcad5a3a47fafbc9eTobin Ehlis if (is_image) { 5382825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis mem_info->bound_images.erase(handle); 53831cba4e1b5940c6818572e05dcad5a3a47fafbc9eTobin Ehlis } else { 5384825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis mem_info->bound_buffers.erase(handle); 53851cba4e1b5940c6818572e05dcad5a3a47fafbc9eTobin Ehlis } 538647aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski} 538747aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski 5388842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinskivoid RemoveBufferMemoryRange(uint64_t handle, DEVICE_MEM_INFO *mem_info) { RemoveMemoryRange(handle, mem_info, false); } 5389825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis 53908c59133586421be878d393799b30044497f77727Mark Lobodzinskivoid RemoveImageMemoryRange(uint64_t handle, DEVICE_MEM_INFO *mem_info) { RemoveMemoryRange(handle, mem_info, true); } 5391825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis 5392bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyBuffer(VkDevice device, VkBuffer buffer, const VkAllocationCallbacks *pAllocator) { 539356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 5394e1056daefb39e3a3fed0088874725c56a1359e54Tobin Ehlis BUFFER_STATE *buffer_state = nullptr; 5395e1056daefb39e3a3fed0088874725c56a1359e54Tobin Ehlis VK_OBJECT obj_struct; 5396b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 5397e1056daefb39e3a3fed0088874725c56a1359e54Tobin Ehlis bool skip = PreCallValidateDestroyBuffer(dev_data, buffer, &buffer_state, &obj_struct); 5398e1056daefb39e3a3fed0088874725c56a1359e54Tobin Ehlis if (!skip) { 5399b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 54004a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyBuffer(device, buffer, pAllocator); 5401e1056daefb39e3a3fed0088874725c56a1359e54Tobin Ehlis lock.lock(); 5402405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (buffer != VK_NULL_HANDLE) { 5403405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyBuffer(dev_data, buffer, buffer_state, obj_struct); 5404405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 540547aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski } 54065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 54075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5408bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyBufferView(VkDevice device, VkBufferView bufferView, const VkAllocationCallbacks *pAllocator) { 540956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 5410f61017735c3291a2665487f2bac310578fc60a68Tobin Ehlis // Common data objects used pre & post call 54118e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis BUFFER_VIEW_STATE *buffer_view_state = nullptr; 54128e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis VK_OBJECT obj_struct; 5413a123662876eebfa844faa65ae3f071d3d77618ebTobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 54148e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis // Validate state before calling down chain, update common data if we'll be calling down chain 54158e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis bool skip = PreCallValidateDestroyBufferView(dev_data, bufferView, &buffer_view_state, &obj_struct); 541638e26abbaa884eb48bfec4ddb4e0ae2c90634e06Tobin Ehlis if (!skip) { 541738e26abbaa884eb48bfec4ddb4e0ae2c90634e06Tobin Ehlis lock.unlock(); 54184a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyBufferView(device, bufferView, pAllocator); 54198e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis lock.lock(); 5420405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (bufferView != VK_NULL_HANDLE) { 5421405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyBufferView(dev_data, bufferView, buffer_view_state, obj_struct); 5422405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 54235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 54245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 54255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 54262a0dd15a44bf665c97a3ff6adcbe7fe5853cdf60Tobin EhlisVKAPI_ATTR void VKAPI_CALL DestroyImage(VkDevice device, VkImage image, const VkAllocationCallbacks *pAllocator) { 542756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 54281facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis IMAGE_STATE *image_state = nullptr; 54292a0dd15a44bf665c97a3ff6adcbe7fe5853cdf60Tobin Ehlis VK_OBJECT obj_struct; 54302a0dd15a44bf665c97a3ff6adcbe7fe5853cdf60Tobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 54312a0dd15a44bf665c97a3ff6adcbe7fe5853cdf60Tobin Ehlis bool skip = PreCallValidateDestroyImage(dev_data, image, &image_state, &obj_struct); 54322a0dd15a44bf665c97a3ff6adcbe7fe5853cdf60Tobin Ehlis if (!skip) { 5433f940225c9e5e3e14b3f5a32d3ea360b585614600Tobin Ehlis lock.unlock(); 54344a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyImage(device, image, pAllocator); 54352a0dd15a44bf665c97a3ff6adcbe7fe5853cdf60Tobin Ehlis lock.lock(); 5436405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (image != VK_NULL_HANDLE) { 5437405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyImage(dev_data, image, image_state, obj_struct); 5438405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 54395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 54405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 54415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 54424261f1e2c91c90ce040ab36a13c9d92f6e988f10Mark Lobodzinskistatic bool ValidateMemoryTypes(const layer_data *dev_data, const DEVICE_MEM_INFO *mem_info, const uint32_t memory_type_bits, 5443f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen const char *funcName, UNIQUE_VALIDATION_ERROR_CODE msgCode) { 54444261f1e2c91c90ce040ab36a13c9d92f6e988f10Mark Lobodzinski bool skip_call = false; 5445de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis if (((1 << mem_info->alloc_info.memoryTypeIndex) & memory_type_bits) == 0) { 5446f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen skip_call = 5447f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 5448f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen reinterpret_cast<const uint64_t &>(mem_info->mem), __LINE__, msgCode, "MT", 5449f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen "%s(): MemoryRequirements->memoryTypeBits (0x%X) for this object type are not compatible with the memory " 5450f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen "type (0x%X) of this memory object 0x%" PRIx64 ". %s", 5451f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen funcName, memory_type_bits, mem_info->alloc_info.memoryTypeIndex, 5452f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen reinterpret_cast<const uint64_t &>(mem_info->mem), validation_error_map[msgCode]); 54534261f1e2c91c90ce040ab36a13c9d92f6e988f10Mark Lobodzinski } 54544261f1e2c91c90ce040ab36a13c9d92f6e988f10Mark Lobodzinski return skip_call; 54554261f1e2c91c90ce040ab36a13c9d92f6e988f10Mark Lobodzinski} 54564261f1e2c91c90ce040ab36a13c9d92f6e988f10Mark Lobodzinski 54579207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Strattonstatic bool PreCallValidateBindBufferMemory(layer_data *dev_data, VkBuffer buffer, VkDeviceMemory mem, VkDeviceSize memoryOffset) { 54589207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton bool skip = false; 5459b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 54609207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton 54619a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto buffer_state = GetBufferState(dev_data, buffer); 54625cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis if (buffer_state) { 54639207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton // Track objects tied to memory 54649207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton uint64_t buffer_handle = reinterpret_cast<uint64_t &>(buffer); 5465c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton skip = ValidateSetMemBinding(dev_data, mem, buffer_handle, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, "vkBindBufferMemory()"); 54662eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis if (!buffer_state->memory_requirements_checked) { 54672eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis // There's not an explicit requirement in the spec to call vkGetBufferMemoryRequirements() prior to calling 54689207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton // BindBufferMemory, but it's implied in that memory being bound must conform with VkMemoryRequirements from 54699207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton // vkGetBufferMemoryRequirements() 54709207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, 54719207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton buffer_handle, __LINE__, DRAWSTATE_INVALID_BUFFER, "DS", 54729207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton "vkBindBufferMemory(): Binding memory to buffer 0x%" PRIxLEAST64 54739207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton " but vkGetBufferMemoryRequirements() has not been called on that buffer.", 54749207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton buffer_handle); 54752eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis // Make the call for them so we can verify the state 54762eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis lock.unlock(); 54779207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton dev_data->dispatch_table.GetBufferMemoryRequirements(dev_data->device, buffer, &buffer_state->requirements); 54782eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis lock.lock(); 54792eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis } 548047aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski 548147aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski // Track and validate bound memory range information 54829a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto mem_info = GetMemObjInfo(dev_data, mem); 548357fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis if (mem_info) { 54849207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton skip |= InsertBufferMemoryRange(dev_data, buffer, mem_info, memoryOffset, buffer_state->requirements, 54859207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton "vkBindBufferMemory()"); 54869207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton skip |= ValidateMemoryTypes(dev_data, mem_info, buffer_state->requirements.memoryTypeBits, "vkBindBufferMemory()", 54879207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton VALIDATION_ERROR_00797); 548847aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski } 548947aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski 54902c905c8b5aca814df6c680348145ca48885f9f69Dustin Graves // Validate memory requirements alignment 54912eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis if (vk_safe_modulo(memoryOffset, buffer_state->requirements.alignment) != 0) { 54929207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 54939207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton 0, __LINE__, VALIDATION_ERROR_02174, "DS", 54949207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton "vkBindBufferMemory(): memoryOffset is 0x%" PRIxLEAST64 54959207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton " but must be an integer multiple of the " 54969207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton "VkMemoryRequirements::alignment value 0x%" PRIxLEAST64 54979207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton ", returned from a call to vkGetBufferMemoryRequirements with buffer. %s", 54989207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton memoryOffset, buffer_state->requirements.alignment, validation_error_map[VALIDATION_ERROR_02174]); 54992c905c8b5aca814df6c680348145ca48885f9f69Dustin Graves } 5500ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller 55012c905c8b5aca814df6c680348145ca48885f9f69Dustin Graves // Validate device limits alignments 5502ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller static const VkBufferUsageFlagBits usage_list[3] = { 5503ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller static_cast<VkBufferUsageFlagBits>(VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT), 5504bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT}; 5505bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski static const char *memory_type[3] = {"texel", "uniform", "storage"}; 5506bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski static const char *offset_name[3] = {"minTexelBufferOffsetAlignment", "minUniformBufferOffsetAlignment", 5507bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "minStorageBufferOffsetAlignment"}; 5508cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski 55099207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton // TODO: vk_validation_stats.py cannot abide braces immediately preceding or following a validation error enum 5510cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // clang-format off 55119207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton static const UNIQUE_VALIDATION_ERROR_CODE msgCode[3] = { VALIDATION_ERROR_00794, VALIDATION_ERROR_00795, 55129207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton VALIDATION_ERROR_00796 }; 5513cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // clang-format on 5514ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller 5515ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller // Keep this one fresh! 5516ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller const VkDeviceSize offset_requirement[3] = { 5517ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller dev_data->phys_dev_properties.properties.limits.minTexelBufferOffsetAlignment, 5518ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller dev_data->phys_dev_properties.properties.limits.minUniformBufferOffsetAlignment, 5519bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski dev_data->phys_dev_properties.properties.limits.minStorageBufferOffsetAlignment}; 55208718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis VkBufferUsageFlags usage = dev_data->bufferMap[buffer].get()->createInfo.usage; 5521ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller 5522ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller for (int i = 0; i < 3; i++) { 5523ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller if (usage & usage_list[i]) { 5524ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller if (vk_safe_modulo(memoryOffset, offset_requirement[i]) != 0) { 55259207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton skip |= log_msg( 5526cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, 5527cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, msgCode[i], "DS", "vkBindBufferMemory(): %s memoryOffset is 0x%" PRIxLEAST64 5528cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " but must be a multiple of " 5529cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "device limit %s 0x%" PRIxLEAST64 ". %s", 5530cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski memory_type[i], memoryOffset, offset_name[i], offset_requirement[i], validation_error_map[msgCode[i]]); 5531ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller } 55322c905c8b5aca814df6c680348145ca48885f9f69Dustin Graves } 55332c905c8b5aca814df6c680348145ca48885f9f69Dustin Graves } 55345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 55359207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton return skip; 55369207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton} 55379207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton 55389207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Strattonstatic void PostCallRecordBindBufferMemory(layer_data *dev_data, VkBuffer buffer, VkDeviceMemory mem, VkDeviceSize memoryOffset) { 55399207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton std::unique_lock<std::mutex> lock(global_lock); 55409207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton auto buffer_state = GetBufferState(dev_data, buffer); 55419207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton if (buffer_state) { 5542c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton // Track objects tied to memory 5543c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton uint64_t buffer_handle = reinterpret_cast<uint64_t &>(buffer); 5544c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton SetMemBinding(dev_data, mem, buffer_handle, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, "vkBindBufferMemory()"); 5545c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton 55469207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton buffer_state->binding.mem = mem; 55479207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton buffer_state->binding.offset = memoryOffset; 55489207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton buffer_state->binding.size = buffer_state->requirements.size; 55499207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton } 55509207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton} 55519207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton 55529207132ef623d47fcbdfeb9ebc796eade35a2f4cCort StrattonVKAPI_ATTR VkResult VKAPI_CALL BindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory mem, VkDeviceSize memoryOffset) { 55539207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 55549207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 55559207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton bool skip = PreCallValidateBindBufferMemory(dev_data, buffer, mem, memoryOffset); 55569207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton if (!skip) { 55574a0754042cf090e131e9e769d8a3633c228625beChris Forbes result = dev_data->dispatch_table.BindBufferMemory(device, buffer, mem, memoryOffset); 55589207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton if (result == VK_SUCCESS) { 55599207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton PostCallRecordBindBufferMemory(dev_data, buffer, mem, memoryOffset); 55609207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton } 55615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 55625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 55635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 55645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5565bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL GetBufferMemoryRequirements(VkDevice device, VkBuffer buffer, 5566bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkMemoryRequirements *pMemoryRequirements) { 556756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 556815caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis dev_data->dispatch_table.GetBufferMemoryRequirements(device, buffer, pMemoryRequirements); 55699a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto buffer_state = GetBufferState(dev_data, buffer); 557015caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis if (buffer_state) { 557115caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis buffer_state->requirements = *pMemoryRequirements; 55722eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis buffer_state->memory_requirements_checked = true; 557315caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis } 55745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 55755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5576bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL GetImageMemoryRequirements(VkDevice device, VkImage image, VkMemoryRequirements *pMemoryRequirements) { 557756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 557815caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis dev_data->dispatch_table.GetImageMemoryRequirements(device, image, pMemoryRequirements); 55799a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_state = GetImageState(dev_data, image); 558015caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis if (image_state) { 558115caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis image_state->requirements = *pMemoryRequirements; 55822eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis image_state->memory_requirements_checked = true; 558315caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis } 55845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 5585593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 5586bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyImageView(VkDevice device, VkImageView imageView, const VkAllocationCallbacks *pAllocator) { 558756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 5588f61017735c3291a2665487f2bac310578fc60a68Tobin Ehlis // Common data objects used pre & post call 5589f61017735c3291a2665487f2bac310578fc60a68Tobin Ehlis IMAGE_VIEW_STATE *image_view_state = nullptr; 5590f61017735c3291a2665487f2bac310578fc60a68Tobin Ehlis VK_OBJECT obj_struct; 5591a123662876eebfa844faa65ae3f071d3d77618ebTobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 5592f61017735c3291a2665487f2bac310578fc60a68Tobin Ehlis bool skip = PreCallValidateDestroyImageView(dev_data, imageView, &image_view_state, &obj_struct); 5593d85c42a6c1d6ad7a6f684c5bd793aab482b7705cTobin Ehlis if (!skip) { 5594d85c42a6c1d6ad7a6f684c5bd793aab482b7705cTobin Ehlis lock.unlock(); 55954a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyImageView(device, imageView, pAllocator); 5596f61017735c3291a2665487f2bac310578fc60a68Tobin Ehlis lock.lock(); 5597405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (imageView != VK_NULL_HANDLE) { 5598405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyImageView(dev_data, imageView, image_view_state, obj_struct); 5599405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 5600d85c42a6c1d6ad7a6f684c5bd793aab482b7705cTobin Ehlis } 56015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 56025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5603bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyShaderModule(VkDevice device, VkShaderModule shaderModule, 5604bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator) { 560556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 5606918c283ac4f8c604b79abd0c8b5706d2a7352a34Chris Forbes 5607b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 560851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->shaderModuleMap.erase(shaderModule); 5609b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 5610918c283ac4f8c604b79abd0c8b5706d2a7352a34Chris Forbes 561151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->dispatch_table.DestroyShaderModule(device, shaderModule, pAllocator); 56125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 56135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 56144c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlisstatic bool PreCallValidateDestroyPipeline(layer_data *dev_data, VkPipeline pipeline, PIPELINE_STATE **pipeline_state, 56158bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis VK_OBJECT *obj_struct) { 561694165f5005d1fa37801d49067fe7751789b89d27Tobin Ehlis *pipeline_state = getPipelineState(dev_data, pipeline); 561794165f5005d1fa37801d49067fe7751789b89d27Tobin Ehlis *obj_struct = {reinterpret_cast<uint64_t &>(pipeline), VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT}; 5618cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_pipeline) return false; 56198bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis bool skip = false; 56208bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis if (*pipeline_state) { 56211803032f91d772ff3589c9f5a51ade5b299ba538Tobin Ehlis skip |= ValidateObjectNotInUse(dev_data, *pipeline_state, *obj_struct, VALIDATION_ERROR_00555); 56228bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis } 56238bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis return skip; 56248bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis} 56258bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis 56264c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlisstatic void PostCallRecordDestroyPipeline(layer_data *dev_data, VkPipeline pipeline, PIPELINE_STATE *pipeline_state, 56278bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis VK_OBJECT obj_struct) { 56288bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis // Any bound cmd buffers are now invalid 562939c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis invalidateCommandBuffers(dev_data, pipeline_state->cb_bindings, obj_struct); 56308bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis dev_data->pipelineMap.erase(pipeline); 56318bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis} 56328bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis 5633bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyPipeline(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks *pAllocator) { 563456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 56354c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis PIPELINE_STATE *pipeline_state = nullptr; 56368bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis VK_OBJECT obj_struct; 5637e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 56388bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis bool skip = PreCallValidateDestroyPipeline(dev_data, pipeline, &pipeline_state, &obj_struct); 5639f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis if (!skip) { 5640f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis lock.unlock(); 56414a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyPipeline(device, pipeline, pAllocator); 56428bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis lock.lock(); 5643405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (pipeline != VK_NULL_HANDLE) { 5644405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyPipeline(dev_data, pipeline, pipeline_state, obj_struct); 5645405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 5646f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis } 56475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 56485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5649bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyPipelineLayout(VkDevice device, VkPipelineLayout pipelineLayout, 5650bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator) { 565156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 5652e28cddb35c63274c13873b9a7060ad43b255c6f1Tobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 56536792ea7cc0ce5fa64b7bd6c946460608cbda91c7Tobin Ehlis dev_data->pipelineLayoutMap.erase(pipelineLayout); 5654e28cddb35c63274c13873b9a7060ad43b255c6f1Tobin Ehlis lock.unlock(); 5655e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis 56564a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyPipelineLayout(device, pipelineLayout, pAllocator); 56575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 56585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5659d31a44af6da568692a73201825459689c9431867Tobin Ehlisstatic bool PreCallValidateDestroySampler(layer_data *dev_data, VkSampler sampler, SAMPLER_STATE **sampler_state, 5660806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis VK_OBJECT *obj_struct) { 56619a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *sampler_state = GetSamplerState(dev_data, sampler); 566294165f5005d1fa37801d49067fe7751789b89d27Tobin Ehlis *obj_struct = {reinterpret_cast<uint64_t &>(sampler), VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT}; 5663cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_sampler) return false; 5664806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis bool skip = false; 5665806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis if (*sampler_state) { 5666806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis skip |= ValidateObjectNotInUse(dev_data, *sampler_state, *obj_struct, VALIDATION_ERROR_00837); 5667806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis } 5668806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis return skip; 5669806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis} 5670806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis 5671d31a44af6da568692a73201825459689c9431867Tobin Ehlisstatic void PostCallRecordDestroySampler(layer_data *dev_data, VkSampler sampler, SAMPLER_STATE *sampler_state, 5672806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis VK_OBJECT obj_struct) { 5673806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis // Any bound cmd buffers are now invalid 5674cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (sampler_state) invalidateCommandBuffers(dev_data, sampler_state->cb_bindings, obj_struct); 5675806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis dev_data->samplerMap.erase(sampler); 5676806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis} 5677806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis 5678bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroySampler(VkDevice device, VkSampler sampler, const VkAllocationCallbacks *pAllocator) { 567956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 5680d31a44af6da568692a73201825459689c9431867Tobin Ehlis SAMPLER_STATE *sampler_state = nullptr; 5681806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis VK_OBJECT obj_struct; 568256f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 5683806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis bool skip = PreCallValidateDestroySampler(dev_data, sampler, &sampler_state, &obj_struct); 5684f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis if (!skip) { 5685f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis lock.unlock(); 56864a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroySampler(device, sampler, pAllocator); 5687806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis lock.lock(); 5688405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (sampler != VK_NULL_HANDLE) { 5689405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroySampler(dev_data, sampler, sampler_state, obj_struct); 5690405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 5691f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis } 56925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 56935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 569479c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlisstatic void PostCallRecordDestroyDescriptorSetLayout(layer_data *dev_data, VkDescriptorSetLayout ds_layout) { 569579c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlis dev_data->descriptorSetLayoutMap.erase(ds_layout); 569679c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlis} 569779c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlis 5698bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyDescriptorSetLayout(VkDevice device, VkDescriptorSetLayout descriptorSetLayout, 5699bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator) { 570056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 570179c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlis dev_data->dispatch_table.DestroyDescriptorSetLayout(device, descriptorSetLayout, pAllocator); 570279c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 570379c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlis PostCallRecordDestroyDescriptorSetLayout(dev_data, descriptorSetLayout); 57045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 57055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5706c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlisstatic bool PreCallValidateDestroyDescriptorPool(layer_data *dev_data, VkDescriptorPool pool, 5707a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis DESCRIPTOR_POOL_STATE **desc_pool_state, VK_OBJECT *obj_struct) { 57089a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *desc_pool_state = GetDescriptorPoolState(dev_data, pool); 570994165f5005d1fa37801d49067fe7751789b89d27Tobin Ehlis *obj_struct = {reinterpret_cast<uint64_t &>(pool), VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT}; 5710cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_descriptor_pool) return false; 5711c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis bool skip = false; 5712c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis if (*desc_pool_state) { 57131803032f91d772ff3589c9f5a51ade5b299ba538Tobin Ehlis skip |= ValidateObjectNotInUse(dev_data, *desc_pool_state, *obj_struct, VALIDATION_ERROR_00901); 5714c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis } 5715c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis return skip; 5716c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis} 5717c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis 5718c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlisstatic void PostCallRecordDestroyDescriptorPool(layer_data *dev_data, VkDescriptorPool descriptorPool, 5719a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis DESCRIPTOR_POOL_STATE *desc_pool_state, VK_OBJECT obj_struct) { 5720c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis // Any bound cmd buffers are now invalid 572139c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis invalidateCommandBuffers(dev_data, desc_pool_state->cb_bindings, obj_struct); 5722c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis // Free sets that were in this pool 5723c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis for (auto ds : desc_pool_state->sets) { 5724c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis freeDescriptorSet(dev_data, ds); 5725c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis } 5726c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis dev_data->descriptorPoolMap.erase(descriptorPool); 5727c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis} 5728c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis 5729bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, 5730bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator) { 573156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 5732a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis DESCRIPTOR_POOL_STATE *desc_pool_state = nullptr; 5733c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis VK_OBJECT obj_struct; 5734c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 5735c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis bool skip = PreCallValidateDestroyDescriptorPool(dev_data, descriptorPool, &desc_pool_state, &obj_struct); 5736c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis if (!skip) { 5737c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis lock.unlock(); 5738c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis dev_data->dispatch_table.DestroyDescriptorPool(device, descriptorPool, pAllocator); 5739c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis lock.lock(); 5740405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (descriptorPool != VK_NULL_HANDLE) { 5741405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyDescriptorPool(dev_data, descriptorPool, desc_pool_state, obj_struct); 5742405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 5743c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis } 57445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 5745bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis// Verify cmdBuffer in given cb_node is not in global in-flight set, and return skip_call result 5746bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis// If this is a secondary command buffer, then make sure its primary is also in-flight 5747bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis// If primary is not in-flight, then remove secondary from global in-flight set 5748bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis// This function is only valid at a point when cmdBuffer is being reset or freed 5749cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlisstatic bool checkCommandBufferInFlight(layer_data *dev_data, const GLOBAL_CB_NODE *cb_node, const char *action, 5750cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlis UNIQUE_VALIDATION_ERROR_CODE error_code) { 5751bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis bool skip_call = false; 5752bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis if (dev_data->globalInFlightCmdBuffers.count(cb_node->commandBuffer)) { 5753bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis // Primary CB or secondary where primary is also in-flight is an error 5754bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis if ((cb_node->createInfo.level != VK_COMMAND_BUFFER_LEVEL_SECONDARY) || 5755bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis (dev_data->globalInFlightCmdBuffers.count(cb_node->primaryCommandBuffer))) { 5756cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlis skip_call |= 5757cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 5758cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlis reinterpret_cast<const uint64_t &>(cb_node->commandBuffer), __LINE__, error_code, "DS", 5759226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "Attempt to %s command buffer (0x%p) which is in use. %s", action, cb_node->commandBuffer, 5760226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis validation_error_map[error_code]); 5761bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis } 5762bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis } 5763bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis return skip_call; 5764bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis} 5765a964cad279f9749cd9ebfc7555247ff3bff26d53Chris Forbes 5766bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis// Iterate over all cmdBuffers in given commandPool and verify that each is not in use 5767cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlisstatic bool checkCommandBuffersInFlight(layer_data *dev_data, COMMAND_POOL_NODE *pPool, const char *action, 5768cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlis UNIQUE_VALIDATION_ERROR_CODE error_code) { 5769bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis bool skip_call = false; 5770a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes for (auto cmd_buffer : pPool->commandBuffers) { 5771a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes if (dev_data->globalInFlightCmdBuffers.count(cmd_buffer)) { 57729a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis skip_call |= checkCommandBufferInFlight(dev_data, GetCBNode(dev_data, cmd_buffer), action, error_code); 5773bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis } 5774bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis } 5775bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis return skip_call; 5776bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis} 57775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5778a01b5eb150981aad061238e64b173d0da8c11140Chris Forbesstatic void clearCommandBuffersInFlight(layer_data *dev_data, COMMAND_POOL_NODE *pPool) { 5779a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes for (auto cmd_buffer : pPool->commandBuffers) { 5780a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes dev_data->globalInFlightCmdBuffers.erase(cmd_buffer); 5781a964cad279f9749cd9ebfc7555247ff3bff26d53Chris Forbes } 5782a964cad279f9749cd9ebfc7555247ff3bff26d53Chris Forbes} 5783a964cad279f9749cd9ebfc7555247ff3bff26d53Chris Forbes 5784bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL FreeCommandBuffers(VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount, 5785bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkCommandBuffer *pCommandBuffers) { 578656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 57875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool skip_call = false; 5788b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 5789c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes 57905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < commandBufferCount; i++) { 57919a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, pCommandBuffers[i]); 57925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Delete CB information structure, and remove from commandBufferMap 57939f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis if (cb_node) { 5794cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlis skip_call |= checkCommandBufferInFlight(dev_data, cb_node, "free", VALIDATION_ERROR_00096); 5795c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes } 5796c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes } 5797c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes 5798cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip_call) return; 5799c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes 58009a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pPool = GetCommandPoolNode(dev_data, commandPool); 5801c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes for (uint32_t i = 0; i < commandBufferCount; i++) { 58029a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, pCommandBuffers[i]); 5803c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes // Delete CB information structure, and remove from commandBufferMap 58049f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis if (cb_node) { 58059f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis dev_data->globalInFlightCmdBuffers.erase(cb_node->commandBuffer); 58065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // reset prior to delete for data clean-up 58079f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis resetCB(dev_data, cb_node->commandBuffer); 58089f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis dev_data->commandBufferMap.erase(cb_node->commandBuffer); 58099f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis delete cb_node; 58105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 58115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 58125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Remove commandBuffer reference from commandPoolMap 5813c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes pPool->commandBuffers.remove(pCommandBuffers[i]); 58145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5815b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 5816e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis 58174a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.FreeCommandBuffers(device, commandPool, commandBufferCount, pCommandBuffers); 58185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 58195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 582089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateCommandPool(VkDevice device, const VkCommandPoolCreateInfo *pCreateInfo, 5821bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkCommandPool *pCommandPool) { 582256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 58235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 58244a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateCommandPool(device, pCreateInfo, pAllocator, pCommandPool); 58255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 58265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 5827b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 58285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->commandPoolMap[*pCommandPool].createFlags = pCreateInfo->flags; 58295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->commandPoolMap[*pCommandPool].queueFamilyIndex = pCreateInfo->queueFamilyIndex; 58305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 58315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 58325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 58335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 583489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateQueryPool(VkDevice device, const VkQueryPoolCreateInfo *pCreateInfo, 583589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkQueryPool *pQueryPool) { 583656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 58370c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis bool skip = false; 58380c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis if (pCreateInfo && pCreateInfo->queryType == VK_QUERY_TYPE_PIPELINE_STATISTICS) { 58390c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis if (!dev_data->enabled_features.pipelineStatisticsQuery) { 58400c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, 58410c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis __LINE__, VALIDATION_ERROR_01006, "DS", 58420c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis "Query pool with type VK_QUERY_TYPE_PIPELINE_STATISTICS created on a device " 58430c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis "with VkDeviceCreateInfo.pEnabledFeatures.pipelineStatisticsQuery == VK_FALSE. %s", 58440c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis validation_error_map[VALIDATION_ERROR_01006]); 58450c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis } 58460c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis } 58470c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis 58480c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 58490c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis if (!skip) { 58500c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis result = dev_data->dispatch_table.CreateQueryPool(device, pCreateInfo, pAllocator, pQueryPool); 58510c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis } 58525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (result == VK_SUCCESS) { 5853b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 5854eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis QUERY_POOL_NODE *qp_node = &dev_data->queryPoolMap[*pQueryPool]; 5855eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis qp_node->createInfo = *pCreateInfo; 58565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 58575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 58585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 58595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 58605f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlisstatic bool PreCallValidateDestroyCommandPool(layer_data *dev_data, VkCommandPool pool, COMMAND_POOL_NODE **cp_state) { 58619a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *cp_state = GetCommandPoolNode(dev_data, pool); 5862cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_command_pool) return false; 58635f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis bool skip = false; 58645f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis if (*cp_state) { 58655f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis // Verify that command buffers in pool are complete (not in-flight) 58665f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis skip |= checkCommandBuffersInFlight(dev_data, *cp_state, "destroy command pool with", VALIDATION_ERROR_00077); 58675f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis } 58685f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis return skip; 58695f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis} 58705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 58715f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlisstatic void PostCallRecordDestroyCommandPool(layer_data *dev_data, VkCommandPool pool, COMMAND_POOL_NODE *cp_state) { 58729f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis // Must remove cmdpool from cmdpoolmap, after removing all cmdbuffers in its list from the commandBufferMap 58735f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis clearCommandBuffersInFlight(dev_data, cp_state); 58745f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis for (auto cb : cp_state->commandBuffers) { 5875a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes clear_cmd_buf_and_mem_references(dev_data, cb); 58769a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, cb); 5877d61de0e68063faa169a9a632f811c9c9adec9897Tobin Ehlis // Remove references to this cb_node prior to delete 5878d61de0e68063faa169a9a632f811c9c9adec9897Tobin Ehlis // TODO : Need better solution here, resetCB? 58797165385f3a39f1f951f3a6a9a06ed2cce4642b6dMark Lobodzinski for (auto obj : cb_node->object_bindings) { 58807165385f3a39f1f951f3a6a9a06ed2cce4642b6dMark Lobodzinski removeCommandBufferBinding(dev_data, &obj, cb_node); 58817165385f3a39f1f951f3a6a9a06ed2cce4642b6dMark Lobodzinski } 5882d61de0e68063faa169a9a632f811c9c9adec9897Tobin Ehlis for (auto framebuffer : cb_node->framebuffers) { 58839a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto fb_state = GetFramebufferState(dev_data, framebuffer); 5884cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (fb_state) fb_state->cb_bindings.erase(cb_node); 5885d61de0e68063faa169a9a632f811c9c9adec9897Tobin Ehlis } 5886cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski dev_data->commandBufferMap.erase(cb); // Remove this command buffer 5887cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski delete cb_node; // delete CB info structure 5888a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes } 58895f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis dev_data->commandPoolMap.erase(pool); 58905f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis} 5891e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis 58925f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis// Destroy commandPool along with all of the commandBuffers allocated from that pool 58935f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin EhlisVKAPI_ATTR void VKAPI_CALL DestroyCommandPool(VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks *pAllocator) { 589456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 58955f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis COMMAND_POOL_NODE *cp_state = nullptr; 58965f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 58975f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis bool skip = PreCallValidateDestroyCommandPool(dev_data, commandPool, &cp_state); 58985f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis if (!skip) { 58995f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis lock.unlock(); 59005f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis dev_data->dispatch_table.DestroyCommandPool(device, commandPool, pAllocator); 59015f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis lock.lock(); 5902405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (commandPool != VK_NULL_HANDLE) { 5903405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyCommandPool(dev_data, commandPool, cp_state); 5904405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 59055f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis } 59065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 59075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5908bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL ResetCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolResetFlags flags) { 590956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 591083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 5911400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis 59121ec6311a8537f4467db08eacbd762ebaa87e70b0Chris Forbes std::unique_lock<std::mutex> lock(global_lock); 59139a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pPool = GetCommandPoolNode(dev_data, commandPool); 5914cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlis skip_call |= checkCommandBuffersInFlight(dev_data, pPool, "reset command pool with", VALIDATION_ERROR_00072); 59151ec6311a8537f4467db08eacbd762ebaa87e70b0Chris Forbes lock.unlock(); 5916a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes 5917cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip_call) return VK_ERROR_VALIDATION_FAILED_EXT; 59185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 59194a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.ResetCommandPool(device, commandPool, flags); 59205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 59215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Reset all of the CBs allocated from this pool 59225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 59231ec6311a8537f4467db08eacbd762ebaa87e70b0Chris Forbes lock.lock(); 5924a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes clearCommandBuffersInFlight(dev_data, pPool); 5925a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes for (auto cmdBuffer : pPool->commandBuffers) { 5926a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes resetCB(dev_data, cmdBuffer); 59275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 59281ec6311a8537f4467db08eacbd762ebaa87e70b0Chris Forbes lock.unlock(); 59295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 59305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 59315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 59325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 593389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL ResetFences(VkDevice device, uint32_t fenceCount, const VkFence *pFences) { 593456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 593583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 5936b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 59375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < fenceCount; ++i) { 59389a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pFence = GetFenceNode(dev_data, pFences[i]); 5939090da73358f71ba026e2474a822fecf55267d166Chris Forbes if (pFence && pFence->state == FENCE_INFLIGHT) { 594083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, 59414527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton reinterpret_cast<const uint64_t &>(pFences[i]), __LINE__, VALIDATION_ERROR_00183, "DS", 59424527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton "Fence 0x%" PRIx64 " is in use. %s", reinterpret_cast<const uint64_t &>(pFences[i]), 59434527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton validation_error_map[VALIDATION_ERROR_00183]); 59445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 59455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5946b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 5947090da73358f71ba026e2474a822fecf55267d166Chris Forbes 5948cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip_call) return VK_ERROR_VALIDATION_FAILED_EXT; 5949090da73358f71ba026e2474a822fecf55267d166Chris Forbes 59504a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.ResetFences(device, fenceCount, pFences); 5951090da73358f71ba026e2474a822fecf55267d166Chris Forbes 5952090da73358f71ba026e2474a822fecf55267d166Chris Forbes if (result == VK_SUCCESS) { 5953090da73358f71ba026e2474a822fecf55267d166Chris Forbes lock.lock(); 5954090da73358f71ba026e2474a822fecf55267d166Chris Forbes for (uint32_t i = 0; i < fenceCount; ++i) { 59559a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pFence = GetFenceNode(dev_data, pFences[i]); 5956090da73358f71ba026e2474a822fecf55267d166Chris Forbes if (pFence) { 5957090da73358f71ba026e2474a822fecf55267d166Chris Forbes pFence->state = FENCE_UNSIGNALED; 5958090da73358f71ba026e2474a822fecf55267d166Chris Forbes } 5959090da73358f71ba026e2474a822fecf55267d166Chris Forbes } 5960090da73358f71ba026e2474a822fecf55267d166Chris Forbes lock.unlock(); 5961090da73358f71ba026e2474a822fecf55267d166Chris Forbes } 5962090da73358f71ba026e2474a822fecf55267d166Chris Forbes 59635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 59645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 59655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5966e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis// For given cb_nodes, invalidate them and track object causing invalidation 59670a4087f99558069e9f6a437ff2dbb5a9c1c22ccaTobin Ehlisvoid invalidateCommandBuffers(const layer_data *dev_data, std::unordered_set<GLOBAL_CB_NODE *> const &cb_nodes, VK_OBJECT obj) { 5968e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis for (auto cb_node : cb_nodes) { 596939c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis if (cb_node->state == CB_RECORDING) { 597039c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 5971fefa20333f94ea75877cca53d0631542cd9d0432Tobin Ehlis (uint64_t)(cb_node->commandBuffer), __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER, "DS", 5972226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "Invalidating a command buffer that's currently being recorded: 0x%p.", cb_node->commandBuffer); 597339c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis } 5974e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis cb_node->state = CB_INVALID; 5975e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis cb_node->broken_bindings.push_back(obj); 5976e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis } 5977e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis} 5978e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis 5979c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlisstatic bool PreCallValidateDestroyFramebuffer(layer_data *dev_data, VkFramebuffer framebuffer, 5980c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis FRAMEBUFFER_STATE **framebuffer_state, VK_OBJECT *obj_struct) { 59819a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *framebuffer_state = GetFramebufferState(dev_data, framebuffer); 598294165f5005d1fa37801d49067fe7751789b89d27Tobin Ehlis *obj_struct = {reinterpret_cast<uint64_t &>(framebuffer), VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT}; 5983cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_framebuffer) return false; 5984728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis bool skip = false; 5985728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis if (*framebuffer_state) { 5986728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis skip |= ValidateObjectNotInUse(dev_data, *framebuffer_state, *obj_struct, VALIDATION_ERROR_00422); 5987728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis } 5988728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis return skip; 5989728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis} 5990728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis 5991c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlisstatic void PostCallRecordDestroyFramebuffer(layer_data *dev_data, VkFramebuffer framebuffer, FRAMEBUFFER_STATE *framebuffer_state, 5992728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis VK_OBJECT obj_struct) { 599339c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis invalidateCommandBuffers(dev_data, framebuffer_state->cb_bindings, obj_struct); 5994728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis dev_data->frameBufferMap.erase(framebuffer); 5995728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis} 5996728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis 5997bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyFramebuffer(VkDevice device, VkFramebuffer framebuffer, const VkAllocationCallbacks *pAllocator) { 599856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 5999c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis FRAMEBUFFER_STATE *framebuffer_state = nullptr; 6000728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis VK_OBJECT obj_struct; 6001b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 6002728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis bool skip = PreCallValidateDestroyFramebuffer(dev_data, framebuffer, &framebuffer_state, &obj_struct); 6003728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis if (!skip) { 6004728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis lock.unlock(); 6005728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis dev_data->dispatch_table.DestroyFramebuffer(device, framebuffer, pAllocator); 6006728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis lock.lock(); 6007405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (framebuffer != VK_NULL_HANDLE) { 6008405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyFramebuffer(dev_data, framebuffer, framebuffer_state, obj_struct); 6009405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 60105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 60115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 60125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 60130ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlisstatic bool PreCallValidateDestroyRenderPass(layer_data *dev_data, VkRenderPass render_pass, RENDER_PASS_STATE **rp_state, 60140ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis VK_OBJECT *obj_struct) { 60159a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *rp_state = GetRenderPassState(dev_data, render_pass); 601694165f5005d1fa37801d49067fe7751789b89d27Tobin Ehlis *obj_struct = {reinterpret_cast<uint64_t &>(render_pass), VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT}; 6017cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_renderpass) return false; 60180ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis bool skip = false; 60190ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis if (*rp_state) { 60200ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis skip |= ValidateObjectNotInUse(dev_data, *rp_state, *obj_struct, VALIDATION_ERROR_00393); 60210ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis } 60220ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis return skip; 60230ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis} 60240ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis 60250ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlisstatic void PostCallRecordDestroyRenderPass(layer_data *dev_data, VkRenderPass render_pass, RENDER_PASS_STATE *rp_state, 60260ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis VK_OBJECT obj_struct) { 602739c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis invalidateCommandBuffers(dev_data, rp_state->cb_bindings, obj_struct); 60280ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis dev_data->renderPassMap.erase(render_pass); 60290ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis} 60300ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis 6031bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyRenderPass(VkDevice device, VkRenderPass renderPass, const VkAllocationCallbacks *pAllocator) { 603256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 60330ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis RENDER_PASS_STATE *rp_state = nullptr; 60340ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis VK_OBJECT obj_struct; 6035e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 60360ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis bool skip = PreCallValidateDestroyRenderPass(dev_data, renderPass, &rp_state, &obj_struct); 6037a9fbfe0c622e9fa4b56ddd015ed4c3c409020c2eTobin Ehlis if (!skip) { 6038a9fbfe0c622e9fa4b56ddd015ed4c3c409020c2eTobin Ehlis lock.unlock(); 60394a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyRenderPass(device, renderPass, pAllocator); 60400ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis lock.lock(); 6041405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (renderPass != VK_NULL_HANDLE) { 6042405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyRenderPass(dev_data, renderPass, rp_state, obj_struct); 6043405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 6044a9fbfe0c622e9fa4b56ddd015ed4c3c409020c2eTobin Ehlis } 60455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 60465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 604789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateBuffer(VkDevice device, const VkBufferCreateInfo *pCreateInfo, 604889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkBuffer *pBuffer) { 604956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 60503683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski std::unique_lock<std::mutex> lock(global_lock); 60513683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski bool skip = PreCallValidateCreateBuffer(dev_data, pCreateInfo); 60523683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski lock.unlock(); 60533683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski 60543683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 60554a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateBuffer(device, pCreateInfo, pAllocator, pBuffer); 60565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 60575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 60583683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski lock.lock(); 60593683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski PostCallRecordCreateBuffer(dev_data, pCreateInfo, pBuffer); 60603683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski lock.unlock(); 60615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 60625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 60635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 60645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 606589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateBufferView(VkDevice device, const VkBufferViewCreateInfo *pCreateInfo, 606689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkBufferView *pView) { 606756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 60688c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young std::unique_lock<std::mutex> lock(global_lock); 60698c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young bool skip_call = PreCallValidateCreateBufferView(dev_data, pCreateInfo); 60708c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young lock.unlock(); 6071cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip_call) return VK_ERROR_VALIDATION_FAILED_EXT; 60724a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateBufferView(device, pCreateInfo, pAllocator, pView); 60735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 60748c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young lock.lock(); 60753683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski PostCallRecordCreateBufferView(dev_data, pCreateInfo, pView); 60768c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young lock.unlock(); 60775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 60785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 60795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 60805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 60818dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski// Access helper functions for external modules 6082d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinskiconst VkFormatProperties *GetFormatProperties(core_validation::layer_data *device_data, VkFormat format) { 6083d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski VkFormatProperties *format_properties = new VkFormatProperties; 6084d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski instance_layer_data *instance_data = 6085d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski GetLayerDataPtr(get_dispatch_key(device_data->instance_data->instance), instance_layer_data_map); 6086d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski instance_data->dispatch_table.GetPhysicalDeviceFormatProperties(device_data->physical_device, format, format_properties); 6087d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski return format_properties; 60888dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski} 60898dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski 6090d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinskiconst VkImageFormatProperties *GetImageFormatProperties(core_validation::layer_data *device_data, VkFormat format, 6091d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski VkImageType image_type, VkImageTiling tiling, VkImageUsageFlags usage, 6092d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski VkImageCreateFlags flags) { 6093d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski VkImageFormatProperties *image_format_properties = new VkImageFormatProperties; 6094d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski instance_layer_data *instance_data = 6095d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski GetLayerDataPtr(get_dispatch_key(device_data->instance_data->instance), instance_layer_data_map); 6096d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski instance_data->dispatch_table.GetPhysicalDeviceImageFormatProperties(device_data->physical_device, format, image_type, tiling, 6097d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski usage, flags, image_format_properties); 6098d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski return image_format_properties; 60998dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski} 61008dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski 61018dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinskiconst debug_report_data *GetReportData(core_validation::layer_data *device_data) { return device_data->report_data; } 61028dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski 61038dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinskiconst VkPhysicalDeviceProperties *GetPhysicalDeviceProperties(core_validation::layer_data *device_data) { 61048dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski return &device_data->phys_dev_props; 61058dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski} 61068dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski 61078c59133586421be878d393799b30044497f77727Mark Lobodzinskiconst CHECK_DISABLED *GetDisables(core_validation::layer_data *device_data) { return &device_data->instance_data->disabled; } 61088c59133586421be878d393799b30044497f77727Mark Lobodzinski 61098c59133586421be878d393799b30044497f77727Mark Lobodzinskistd::unordered_map<VkImage, std::unique_ptr<IMAGE_STATE>> *GetImageMap(core_validation::layer_data *device_data) { 61108c59133586421be878d393799b30044497f77727Mark Lobodzinski return &device_data->imageMap; 61118c59133586421be878d393799b30044497f77727Mark Lobodzinski} 61128c59133586421be878d393799b30044497f77727Mark Lobodzinski 61138c59133586421be878d393799b30044497f77727Mark Lobodzinskistd::unordered_map<VkImage, std::vector<ImageSubresourcePair>> *GetImageSubresourceMap(core_validation::layer_data *device_data) { 61148c59133586421be878d393799b30044497f77727Mark Lobodzinski return &device_data->imageSubresourceMap; 61158c59133586421be878d393799b30044497f77727Mark Lobodzinski} 61168c59133586421be878d393799b30044497f77727Mark Lobodzinski 61178c59133586421be878d393799b30044497f77727Mark Lobodzinskistd::unordered_map<ImageSubresourcePair, IMAGE_LAYOUT_NODE> *GetImageLayoutMap(layer_data *device_data) { 61188c59133586421be878d393799b30044497f77727Mark Lobodzinski return &device_data->imageLayoutMap; 61198c59133586421be878d393799b30044497f77727Mark Lobodzinski} 61208c59133586421be878d393799b30044497f77727Mark Lobodzinski 61213683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinskistd::unordered_map<VkBuffer, std::unique_ptr<BUFFER_STATE>> *GetBufferMap(layer_data *device_data) { 61223683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski return &device_data->bufferMap; 61233683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski} 61243683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski 61253683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinskistd::unordered_map<VkBufferView, std::unique_ptr<BUFFER_VIEW_STATE>> *GetBufferViewMap(layer_data *device_data) { 61263683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski return &device_data->bufferViewMap; 61273683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski} 61283683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski 61291c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinskistd::unordered_map<VkImageView, std::unique_ptr<IMAGE_VIEW_STATE>> *GetImageViewMap(layer_data *device_data) { 61301c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski return &device_data->imageViewMap; 61311c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski} 61321c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski 6133d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinskiconst PHYS_DEV_PROPERTIES_NODE *GetPhysDevProperties(const layer_data *device_data) { 61346a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski return &device_data->phys_dev_properties; 61356a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski} 61366a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski 613789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo, 613889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkImage *pImage) { 61398dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 614056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 61418dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski bool skip = PreCallValidateCreateImage(dev_data, pCreateInfo, pAllocator, pImage); 61428dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski if (!skip) { 61438dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski result = dev_data->dispatch_table.CreateImage(device, pCreateInfo, pAllocator, pImage); 61448dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski } 61455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 6146b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 6147920311b6aa5614a545cad59521770d0898a75d65Mark Lobodzinski PostCallRecordCreateImage(dev_data, pCreateInfo, pImage); 61485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 61495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 61505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 61515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 61528c07a094dc9cc4afb6b62181f341c12b9e969041Mark YoungVKAPI_ATTR VkResult VKAPI_CALL CreateImageView(VkDevice device, const VkImageViewCreateInfo *pCreateInfo, 61538c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young const VkAllocationCallbacks *pAllocator, VkImageView *pView) { 615456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 61558c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young std::unique_lock<std::mutex> lock(global_lock); 6156e3effabf8e97cae8e006477806ceaca62e4f2ce7Tobin Ehlis bool skip = PreCallValidateCreateImageView(dev_data, pCreateInfo); 61578c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young lock.unlock(); 6158cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 61594a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateImageView(device, pCreateInfo, pAllocator, pView); 61605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 61618c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young lock.lock(); 616279fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis PostCallRecordCreateImageView(dev_data, pCreateInfo, *pView); 61638c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young lock.unlock(); 61645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6165bb6624cb996175d8945190886a200e720b3871efChris Forbes 61665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 61675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 61685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6169bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateFence(VkDevice device, const VkFenceCreateInfo *pCreateInfo, 6170bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkFence *pFence) { 617156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 61724a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateFence(device, pCreateInfo, pAllocator, pFence); 61735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 6174b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 6175a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis auto &fence_node = dev_data->fenceMap[*pFence]; 61768988ad37ea5a054ff2ae3cbe4b767ae6c13cf48bChris Forbes fence_node.fence = *pFence; 6177a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis fence_node.createInfo = *pCreateInfo; 6178cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes fence_node.state = (pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT) ? FENCE_RETIRED : FENCE_UNSIGNALED; 61795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 61805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 61815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 61825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 61835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// TODO handle pipeline caches 618489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreatePipelineCache(VkDevice device, const VkPipelineCacheCreateInfo *pCreateInfo, 618589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkPipelineCache *pPipelineCache) { 618656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 61874a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreatePipelineCache(device, pCreateInfo, pAllocator, pPipelineCache); 61885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 61895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 61905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6191bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyPipelineCache(VkDevice device, VkPipelineCache pipelineCache, 6192bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator) { 619356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 61944a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyPipelineCache(device, pipelineCache, pAllocator); 61955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 61965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6197bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL GetPipelineCacheData(VkDevice device, VkPipelineCache pipelineCache, size_t *pDataSize, 6198bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski void *pData) { 619956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 62004a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.GetPipelineCacheData(device, pipelineCache, pDataSize, pData); 62015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 62025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 62035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6204bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL MergePipelineCaches(VkDevice device, VkPipelineCache dstCache, uint32_t srcCacheCount, 6205bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkPipelineCache *pSrcCaches) { 620656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 62074a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.MergePipelineCaches(device, dstCache, srcCacheCount, pSrcCaches); 62085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 62095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 62105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 62113d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis// utility function to set collective state for pipeline 62124c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlisvoid set_pipeline_state(PIPELINE_STATE *pPipe) { 62133d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis // If any attachment used by this pipeline has blendEnable, set top-level blendEnable 62143d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis if (pPipe->graphicsPipelineCI.pColorBlendState) { 62153d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis for (size_t i = 0; i < pPipe->attachments.size(); ++i) { 62163d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis if (VK_TRUE == pPipe->attachments[i].blendEnable) { 62173d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis if (((pPipe->attachments[i].dstAlphaBlendFactor >= VK_BLEND_FACTOR_CONSTANT_COLOR) && 62183d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis (pPipe->attachments[i].dstAlphaBlendFactor <= VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA)) || 62193d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis ((pPipe->attachments[i].dstColorBlendFactor >= VK_BLEND_FACTOR_CONSTANT_COLOR) && 62203d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis (pPipe->attachments[i].dstColorBlendFactor <= VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA)) || 62213d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis ((pPipe->attachments[i].srcAlphaBlendFactor >= VK_BLEND_FACTOR_CONSTANT_COLOR) && 62223d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis (pPipe->attachments[i].srcAlphaBlendFactor <= VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA)) || 62233d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis ((pPipe->attachments[i].srcColorBlendFactor >= VK_BLEND_FACTOR_CONSTANT_COLOR) && 62243d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis (pPipe->attachments[i].srcColorBlendFactor <= VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA))) { 62253d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis pPipe->blendConstantsEnabled = true; 62263d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 62273d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 62283d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 62293d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 62303d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis} 62313d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis 623248b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinskistatic bool PreCallCreateGraphicsPipelines(layer_data *device_data, uint32_t count, 623348b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinski const VkGraphicsPipelineCreateInfo *create_infos, vector<PIPELINE_STATE *> &pipe_state) { 623448b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinski bool skip = false; 6235bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski instance_layer_data *instance_data = 623656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis GetLayerDataPtr(get_dispatch_key(device_data->instance_data->instance), instance_layer_data_map); 623748b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinski 623848b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinski for (uint32_t i = 0; i < count; i++) { 623948b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinski skip |= verifyPipelineCreateState(device_data, pipe_state, i); 624078b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski if (create_infos[i].pVertexInputState != NULL) { 624178b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski for (uint32_t j = 0; j < create_infos[i].pVertexInputState->vertexAttributeDescriptionCount; j++) { 624278b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski VkFormat format = create_infos[i].pVertexInputState->pVertexAttributeDescriptions[j].format; 624378b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski // Internal call to get format info. Still goes through layers, could potentially go directly to ICD. 624478b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski VkFormatProperties properties; 624578b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski instance_data->dispatch_table.GetPhysicalDeviceFormatProperties(device_data->physical_device, format, &properties); 624678b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski if ((properties.bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) == 0) { 624778b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski skip |= log_msg( 624878b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 624978b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski __LINE__, VALIDATION_ERROR_01413, "IMAGE", 625078b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski "vkCreateGraphicsPipelines: pCreateInfo[%d].pVertexInputState->vertexAttributeDescriptions[%d].format " 625178b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski "(%s) is not a supported vertex buffer format. %s", 625278b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski i, j, string_VkFormat(format), validation_error_map[VALIDATION_ERROR_01413]); 625378b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski } 625478b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski } 625578b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski } 625648b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinski } 625748b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinski return skip; 625848b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinski} 625948b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinski 6260bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count, 6261bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkGraphicsPipelineCreateInfo *pCreateInfos, 6262bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines) { 62635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODO What to do with pipelineCache? 62645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // The order of operations here is a little convoluted but gets the job done 62654c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis // 1. Pipeline create state is first shadowed into PIPELINE_STATE struct 62665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // 2. Create state is then validated (which uses flags setup during shadowing) 62675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // 3. If everything looks good, we'll then create the pipeline and add NODE to pipelineMap 626842486a20f07b16f0c5361cdc00fd789b07b1989aMark Lobodzinski bool skip = false; 62695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODO : Improve this data struct w/ unique_ptrs so cleanup below is automatic 627042486a20f07b16f0c5361cdc00fd789b07b1989aMark Lobodzinski vector<PIPELINE_STATE *> pipe_state(count); 627156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 62725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 62735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t i = 0; 6274b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 62755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 62765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (i = 0; i < count; i++) { 627742486a20f07b16f0c5361cdc00fd789b07b1989aMark Lobodzinski pipe_state[i] = new PIPELINE_STATE; 627842486a20f07b16f0c5361cdc00fd789b07b1989aMark Lobodzinski pipe_state[i]->initGraphicsPipeline(&pCreateInfos[i]); 62799a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis pipe_state[i]->render_pass_ci.initialize(GetRenderPassState(dev_data, pCreateInfos[i].renderPass)->createInfo.ptr()); 628042486a20f07b16f0c5361cdc00fd789b07b1989aMark Lobodzinski pipe_state[i]->pipeline_layout = *getPipelineLayout(dev_data, pCreateInfos[i].layout); 62815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 628242486a20f07b16f0c5361cdc00fd789b07b1989aMark Lobodzinski skip |= PreCallCreateGraphicsPipelines(dev_data, count, pCreateInfos, pipe_state); 62835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6284c70226063be6148056ceeccf835175a1fd59f24fChris Forbes if (skip) { 6285c70226063be6148056ceeccf835175a1fd59f24fChris Forbes for (i = 0; i < count; i++) { 6286c70226063be6148056ceeccf835175a1fd59f24fChris Forbes delete pipe_state[i]; 62871ab616b32d4e5b7d62d4a8c41b0c03ea335ab845Chris Forbes pPipelines[i] = VK_NULL_HANDLE; 6288c70226063be6148056ceeccf835175a1fd59f24fChris Forbes } 62897a456d188475c23b566334be45dc0489b2789653Chris Forbes return VK_ERROR_VALIDATION_FAILED_EXT; 62907a456d188475c23b566334be45dc0489b2789653Chris Forbes } 62917a456d188475c23b566334be45dc0489b2789653Chris Forbes 62927a456d188475c23b566334be45dc0489b2789653Chris Forbes lock.unlock(); 6293bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto result = 6294bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski dev_data->dispatch_table.CreateGraphicsPipelines(device, pipelineCache, count, pCreateInfos, pAllocator, pPipelines); 62957a456d188475c23b566334be45dc0489b2789653Chris Forbes lock.lock(); 62967a456d188475c23b566334be45dc0489b2789653Chris Forbes for (i = 0; i < count; i++) { 629761943a7503bc8594338f3364ef42f1d863486c04Chris Forbes if (pPipelines[i] == VK_NULL_HANDLE) { 629861943a7503bc8594338f3364ef42f1d863486c04Chris Forbes delete pipe_state[i]; 6299bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski } else { 630061943a7503bc8594338f3364ef42f1d863486c04Chris Forbes pipe_state[i]->pipeline = pPipelines[i]; 630161943a7503bc8594338f3364ef42f1d863486c04Chris Forbes dev_data->pipelineMap[pipe_state[i]->pipeline] = pipe_state[i]; 630261943a7503bc8594338f3364ef42f1d863486c04Chris Forbes } 63035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6304c70226063be6148056ceeccf835175a1fd59f24fChris Forbes 63055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 63065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 63075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6308bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count, 6309bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkComputePipelineCreateInfo *pCreateInfos, 6310bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines) { 63110108a1af0b7c6949846e9d71d00bbfb322b6f7caChris Forbes bool skip = false; 63125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 63135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODO : Improve this data struct w/ unique_ptrs so cleanup below is automatic 63144c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis vector<PIPELINE_STATE *> pPipeState(count); 631556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 63165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 63175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t i = 0; 6318b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 63195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (i = 0; i < count; i++) { 63205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODO: Verify compute stage bits 63215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 63225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Create and initialize internal tracking data structure 63234c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis pPipeState[i] = new PIPELINE_STATE; 63244c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis pPipeState[i]->initComputePipeline(&pCreateInfos[i]); 6325c2a5a36d03bbe52f5854a5884346e4a84115e259Tobin Ehlis pPipeState[i]->pipeline_layout = *getPipelineLayout(dev_data, pCreateInfos[i].layout); 63265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 63275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODO: Add Compute Pipeline Verification 63280108a1af0b7c6949846e9d71d00bbfb322b6f7caChris Forbes skip |= !validate_compute_pipeline(dev_data->report_data, pPipeState[i], &dev_data->enabled_features, 6329bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski dev_data->shaderModuleMap); 63300108a1af0b7c6949846e9d71d00bbfb322b6f7caChris Forbes // skip |= verifyPipelineCreateState(dev_data, pPipeState[i]); 63315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 63325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 63337a456d188475c23b566334be45dc0489b2789653Chris Forbes if (skip) { 63345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (i = 0; i < count; i++) { 63355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Clean up any locally allocated data structures 63364c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis delete pPipeState[i]; 6337fcf67c021fdfcbeb12fb04daa9a69ecd7d376c5cChris Forbes pPipelines[i] = VK_NULL_HANDLE; 63385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 63395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return VK_ERROR_VALIDATION_FAILED_EXT; 63405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 63417a456d188475c23b566334be45dc0489b2789653Chris Forbes 63427a456d188475c23b566334be45dc0489b2789653Chris Forbes lock.unlock(); 6343bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto result = 6344bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski dev_data->dispatch_table.CreateComputePipelines(device, pipelineCache, count, pCreateInfos, pAllocator, pPipelines); 63457a456d188475c23b566334be45dc0489b2789653Chris Forbes lock.lock(); 63467a456d188475c23b566334be45dc0489b2789653Chris Forbes for (i = 0; i < count; i++) { 6347fcf67c021fdfcbeb12fb04daa9a69ecd7d376c5cChris Forbes if (pPipelines[i] == VK_NULL_HANDLE) { 6348fcf67c021fdfcbeb12fb04daa9a69ecd7d376c5cChris Forbes delete pPipeState[i]; 6349bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski } else { 6350fcf67c021fdfcbeb12fb04daa9a69ecd7d376c5cChris Forbes pPipeState[i]->pipeline = pPipelines[i]; 6351fcf67c021fdfcbeb12fb04daa9a69ecd7d376c5cChris Forbes dev_data->pipelineMap[pPipeState[i]->pipeline] = pPipeState[i]; 6352fcf67c021fdfcbeb12fb04daa9a69ecd7d376c5cChris Forbes } 63537a456d188475c23b566334be45dc0489b2789653Chris Forbes } 63547a456d188475c23b566334be45dc0489b2789653Chris Forbes 63555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 63565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 63575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 635889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateSampler(VkDevice device, const VkSamplerCreateInfo *pCreateInfo, 635989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkSampler *pSampler) { 636056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 63614a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateSampler(device, pCreateInfo, pAllocator, pSampler); 63625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 6363b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 6364d31a44af6da568692a73201825459689c9431867Tobin Ehlis dev_data->samplerMap[*pSampler] = unique_ptr<SAMPLER_STATE>(new SAMPLER_STATE(pSampler, pCreateInfo)); 63655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 63665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 63675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 63685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 63690c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlisstatic bool PreCallValidateCreateDescriptorSetLayout(layer_data *dev_data, const VkDescriptorSetLayoutCreateInfo *create_info) { 6370cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.create_descriptor_set_layout) return false; 63710c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis return cvdescriptorset::DescriptorSetLayout::ValidateCreateInfo(dev_data->report_data, create_info); 63720c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis} 63730c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis 63740c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlisstatic void PostCallRecordCreateDescriptorSetLayout(layer_data *dev_data, const VkDescriptorSetLayoutCreateInfo *create_info, 63750c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis VkDescriptorSetLayout set_layout) { 63763f1d2ba6852cf6b1bb4e1f06d690293565108e2cTobin Ehlis // TODO: Convert this to unique_ptr to avoid leaks 63770c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis dev_data->descriptorSetLayoutMap[set_layout] = new cvdescriptorset::DescriptorSetLayout(create_info, set_layout); 63780c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis} 63790c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis 6380bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateDescriptorSetLayout(VkDevice device, const VkDescriptorSetLayoutCreateInfo *pCreateInfo, 6381bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, 6382bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDescriptorSetLayout *pSetLayout) { 638356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 63840c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 63850c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 63860c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis bool skip = PreCallValidateCreateDescriptorSetLayout(dev_data, pCreateInfo); 63870c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis if (!skip) { 63880c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis lock.unlock(); 63890c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis result = dev_data->dispatch_table.CreateDescriptorSetLayout(device, pCreateInfo, pAllocator, pSetLayout); 63900c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis if (VK_SUCCESS == result) { 63910c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis lock.lock(); 63920c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis PostCallRecordCreateDescriptorSetLayout(dev_data, pCreateInfo, *pSetLayout); 63930c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis } 63945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 63955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 63965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 63975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 63989e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz// Used by CreatePipelineLayout and CmdPushConstants. 63999e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz// Note that the index argument is optional and only used by CreatePipelineLayout. 64009e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultzstatic bool validatePushConstantRange(const layer_data *dev_data, const uint32_t offset, const uint32_t size, 64019e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz const char *caller_name, uint32_t index = 0) { 6402cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.push_constant_range) return false; 64039e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz uint32_t const maxPushConstantsSize = dev_data->phys_dev_properties.properties.limits.maxPushConstantsSize; 640483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 64059e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz // Check that offset + size don't exceed the max. 64069e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz // Prevent arithetic overflow here by avoiding addition and testing in this order. 64079e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz if ((offset >= maxPushConstantsSize) || (size > maxPushConstantsSize - offset)) { 64089e24d8153ab63bc3ac08b5a1517c203930b5de91Karl 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. 64099e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz if (0 == strcmp(caller_name, "vkCreatePipelineLayout()")) { 6410e420dd92dcfc04f279e98796a49ee26b2c3ddafeTobin Ehlis if (offset >= maxPushConstantsSize) { 6411e420dd92dcfc04f279e98796a49ee26b2c3ddafeTobin Ehlis skip_call |= 6412e420dd92dcfc04f279e98796a49ee26b2c3ddafeTobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 6413cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VALIDATION_ERROR_00877, "DS", 6414cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s call has push constants index %u with offset %u that " 6415cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "exceeds this device's maxPushConstantSize of %u. %s", 6416e420dd92dcfc04f279e98796a49ee26b2c3ddafeTobin Ehlis caller_name, index, offset, maxPushConstantsSize, validation_error_map[VALIDATION_ERROR_00877]); 6417e420dd92dcfc04f279e98796a49ee26b2c3ddafeTobin Ehlis } 6418e420dd92dcfc04f279e98796a49ee26b2c3ddafeTobin Ehlis if (size > maxPushConstantsSize - offset) { 6419e420dd92dcfc04f279e98796a49ee26b2c3ddafeTobin Ehlis skip_call |= 6420e420dd92dcfc04f279e98796a49ee26b2c3ddafeTobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 6421cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VALIDATION_ERROR_00880, "DS", 6422cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s call has push constants index %u with offset %u and size %u that " 6423cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "exceeds this device's maxPushConstantSize of %u. %s", 6424e420dd92dcfc04f279e98796a49ee26b2c3ddafeTobin Ehlis caller_name, index, offset, size, maxPushConstantsSize, validation_error_map[VALIDATION_ERROR_00880]); 6425e420dd92dcfc04f279e98796a49ee26b2c3ddafeTobin Ehlis } 64269e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } else if (0 == strcmp(caller_name, "vkCmdPushConstants()")) { 64274527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton if (offset >= maxPushConstantsSize) { 64284527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton skip_call |= 64294527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 6430cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VALIDATION_ERROR_00991, "DS", 6431cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s call has push constants index %u with offset %u that " 6432cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "exceeds this device's maxPushConstantSize of %u. %s", 64334527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton caller_name, index, offset, maxPushConstantsSize, validation_error_map[VALIDATION_ERROR_00991]); 64344527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton } 64354527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton if (size > maxPushConstantsSize - offset) { 64364527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton skip_call |= 64374527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 6438cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VALIDATION_ERROR_00992, "DS", 6439cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s call has push constants index %u with offset %u and size %u that " 6440cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "exceeds this device's maxPushConstantSize of %u. %s", 64414527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton caller_name, index, offset, size, maxPushConstantsSize, validation_error_map[VALIDATION_ERROR_00992]); 64424527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton } 64439e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } else { 644483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 644583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis DRAWSTATE_INTERNAL_ERROR, "DS", "%s caller not supported.", caller_name); 64469e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 64479e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 64489e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz // size needs to be non-zero and a multiple of 4. 64499e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz if ((size == 0) || ((size & 0x3) != 0)) { 64509e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz if (0 == strcmp(caller_name, "vkCreatePipelineLayout()")) { 6451891f13be101e95697e5af9503f06da38b0c48f79Tobin Ehlis if (size == 0) { 6452891f13be101e95697e5af9503f06da38b0c48f79Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 6453cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, VALIDATION_ERROR_00878, "DS", 6454cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s call has push constants index %u with " 6455cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "size %u. Size must be greater than zero. %s", 6456891f13be101e95697e5af9503f06da38b0c48f79Tobin Ehlis caller_name, index, size, validation_error_map[VALIDATION_ERROR_00878]); 6457891f13be101e95697e5af9503f06da38b0c48f79Tobin Ehlis } 6458891f13be101e95697e5af9503f06da38b0c48f79Tobin Ehlis if (size & 0x3) { 6459891f13be101e95697e5af9503f06da38b0c48f79Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 6460cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, VALIDATION_ERROR_00879, "DS", 6461cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s call has push constants index %u with " 6462cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "size %u. Size must be a multiple of 4. %s", 6463891f13be101e95697e5af9503f06da38b0c48f79Tobin Ehlis caller_name, index, size, validation_error_map[VALIDATION_ERROR_00879]); 6464891f13be101e95697e5af9503f06da38b0c48f79Tobin Ehlis } 64659e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } else if (0 == strcmp(caller_name, "vkCmdPushConstants()")) { 64664527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton if (size == 0) { 64674527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 6468cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, VALIDATION_ERROR_01000, "DS", 6469cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s call has push constants index %u with " 6470cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "size %u. Size must be greater than zero. %s", 64714527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton caller_name, index, size, validation_error_map[VALIDATION_ERROR_01000]); 64724527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton } 64734527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton if (size & 0x3) { 64744527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 6475cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, VALIDATION_ERROR_00990, "DS", 6476cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s call has push constants index %u with " 6477cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "size %u. Size must be a multiple of 4. %s", 64784527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton caller_name, index, size, validation_error_map[VALIDATION_ERROR_00990]); 64794527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton } 64809e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } else { 648183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 648283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis DRAWSTATE_INTERNAL_ERROR, "DS", "%s caller not supported.", caller_name); 64839e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 64849e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 64859e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz // offset needs to be a multiple of 4. 64869e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz if ((offset & 0x3) != 0) { 64879e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz if (0 == strcmp(caller_name, "vkCreatePipelineLayout()")) { 648883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 6489cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VALIDATION_ERROR_02521, "DS", 6490cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s call has push constants index %u with " 6491cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "offset %u. Offset must be a multiple of 4. %s", 64924527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton caller_name, index, offset, validation_error_map[VALIDATION_ERROR_02521]); 64939e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } else if (0 == strcmp(caller_name, "vkCmdPushConstants()")) { 649483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 6495cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VALIDATION_ERROR_00989, "DS", 6496cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s call has push constants with " 6497cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "offset %u. Offset must be a multiple of 4. %s", 64984527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton caller_name, offset, validation_error_map[VALIDATION_ERROR_00989]); 64999e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } else { 650083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 650183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis DRAWSTATE_INTERNAL_ERROR, "DS", "%s caller not supported.", caller_name); 65029e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 65035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 650483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis return skip_call; 65055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 65065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6507bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo, 650889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout) { 650983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 651056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 65111c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis // TODO : Add checks for VALIDATION_ERRORS 865-871 65129e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz // Push Constant Range checks 651307a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz uint32_t i, j; 65145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (i = 0; i < pCreateInfo->pushConstantRangeCount; ++i) { 651583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= validatePushConstantRange(dev_data, pCreateInfo->pPushConstantRanges[i].offset, 651683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis pCreateInfo->pPushConstantRanges[i].size, "vkCreatePipelineLayout()", i); 65179e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz if (0 == pCreateInfo->pPushConstantRanges[i].stageFlags) { 651883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 65194527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton VALIDATION_ERROR_00882, "DS", "vkCreatePipelineLayout() call has no stageFlags set. %s", 65204527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton validation_error_map[VALIDATION_ERROR_00882]); 65219e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 65229e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 6523cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip_call) return VK_ERROR_VALIDATION_FAILED_EXT; 652407a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz 65259e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz // Each range has been validated. Now check for overlap between ranges (if they are good). 652607a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz // There's no explicit Valid Usage language against this, so issue a warning instead of an error. 652707a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz for (i = 0; i < pCreateInfo->pushConstantRangeCount; ++i) { 652807a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz for (j = i + 1; j < pCreateInfo->pushConstantRangeCount; ++j) { 652907a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz const uint32_t minA = pCreateInfo->pPushConstantRanges[i].offset; 653007a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz const uint32_t maxA = minA + pCreateInfo->pPushConstantRanges[i].size; 653107a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz const uint32_t minB = pCreateInfo->pPushConstantRanges[j].offset; 653207a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz const uint32_t maxB = minB + pCreateInfo->pPushConstantRanges[j].size; 653307a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz if ((minA <= minB && maxA > minB) || (minB <= minA && maxB > minA)) { 6534cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 6535cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, DRAWSTATE_PUSH_CONSTANTS_ERROR, "DS", 6536cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkCreatePipelineLayout() call has push constants with " 6537cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "overlapping ranges: %u:[%u, %u), %u:[%u, %u)", 6538cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski i, minA, maxA, j, minB, maxB); 65399e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 65405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 65415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6542f73b2046273413ea1338dd714d67c39f8e0fa09eChris Forbes 65434a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout); 65445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 6545b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 65465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis PIPELINE_LAYOUT_NODE &plNode = dev_data->pipelineLayoutMap[*pPipelineLayout]; 654769b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis plNode.layout = *pPipelineLayout; 6548416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis plNode.set_layouts.resize(pCreateInfo->setLayoutCount); 65495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (i = 0; i < pCreateInfo->setLayoutCount; ++i) { 65509a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis plNode.set_layouts[i] = GetDescriptorSetLayout(dev_data, pCreateInfo->pSetLayouts[i]); 65515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6552416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis plNode.push_constant_ranges.resize(pCreateInfo->pushConstantRangeCount); 65535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (i = 0; i < pCreateInfo->pushConstantRangeCount; ++i) { 6554416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis plNode.push_constant_ranges[i] = pCreateInfo->pPushConstantRanges[i]; 65555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 65565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 65575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 65585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 65595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6560bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateDescriptorPool(VkDevice device, const VkDescriptorPoolCreateInfo *pCreateInfo, 6561bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkDescriptorPool *pDescriptorPool) { 656256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 65634a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateDescriptorPool(device, pCreateInfo, pAllocator, pDescriptorPool); 65645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 65655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, 6566414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller (uint64_t)*pDescriptorPool, __LINE__, DRAWSTATE_OUT_OF_MEMORY, "DS", "Created Descriptor Pool 0x%" PRIxLEAST64, 65675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (uint64_t)*pDescriptorPool)) 65685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return VK_ERROR_VALIDATION_FAILED_EXT; 6569a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis DESCRIPTOR_POOL_STATE *pNewNode = new DESCRIPTOR_POOL_STATE(*pDescriptorPool, pCreateInfo); 65705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (NULL == pNewNode) { 65715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, 65725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (uint64_t)*pDescriptorPool, __LINE__, DRAWSTATE_OUT_OF_MEMORY, "DS", 6573a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis "Out of memory while attempting to allocate DESCRIPTOR_POOL_STATE in vkCreateDescriptorPool()")) 65745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return VK_ERROR_VALIDATION_FAILED_EXT; 65755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 6576b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 65775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->descriptorPoolMap[*pDescriptorPool] = pNewNode; 65785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 65795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 65805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Need to do anything if pool create fails? 65815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 65825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 65835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 65845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6585bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL ResetDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, 6586bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDescriptorPoolResetFlags flags) { 65877286e20c06011d3c6fa7edfbdbadd42bb6e8cc35Tobin Ehlis // TODO : Add checks for VALIDATION_ERROR_00928 658856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 65894a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.ResetDescriptorPool(device, descriptorPool, flags); 65905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 6591b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 65925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis clearDescriptorPool(dev_data, device, descriptorPool, flags); 65935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 65945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 65955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 65962c4e180a4442f968b44f3d5136f7ffda706f6428Chris Forbes// Ensure the pool contains enough descriptors and descriptor sets to satisfy 6597789832b514862c7a7b5b847eeb8e7cacb733b77bTobin Ehlis// an allocation request. Fills common_data with the total number of descriptors of each type required, 6598789832b514862c7a7b5b847eeb8e7cacb733b77bTobin Ehlis// as well as DescriptorSetLayout ptrs used for later update. 65997f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlisstatic bool PreCallValidateAllocateDescriptorSets(layer_data *dev_data, const VkDescriptorSetAllocateInfo *pAllocateInfo, 66007f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlis cvdescriptorset::AllocateDescriptorSetsData *common_data) { 6601cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.allocate_descriptor_sets) return false; 66027e73e5c6b3020b96a821985f73012f2af0f1b992Tobin Ehlis // All state checks for AllocateDescriptorSets is done in single function 6603e3f7c45fd64a44a67ce96c89e2bbee426c6ecf24Tobin Ehlis return cvdescriptorset::ValidateAllocateDescriptorSets(dev_data->report_data, pAllocateInfo, dev_data, common_data); 66047e73e5c6b3020b96a821985f73012f2af0f1b992Tobin Ehlis} 66057e73e5c6b3020b96a821985f73012f2af0f1b992Tobin Ehlis// Allocation state was good and call down chain was made so update state based on allocating descriptor sets 66067e73e5c6b3020b96a821985f73012f2af0f1b992Tobin Ehlisstatic void PostCallRecordAllocateDescriptorSets(layer_data *dev_data, const VkDescriptorSetAllocateInfo *pAllocateInfo, 66077f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlis VkDescriptorSet *pDescriptorSets, 66087f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlis const cvdescriptorset::AllocateDescriptorSetsData *common_data) { 66097e73e5c6b3020b96a821985f73012f2af0f1b992Tobin Ehlis // All the updates are contained in a single cvdescriptorset function 66102c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis cvdescriptorset::PerformAllocateDescriptorSets(pAllocateInfo, pDescriptorSets, common_data, &dev_data->descriptorPoolMap, 6611b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis &dev_data->setMap, dev_data); 66122c4e180a4442f968b44f3d5136f7ffda706f6428Chris Forbes} 66132c4e180a4442f968b44f3d5136f7ffda706f6428Chris Forbes 6614bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL AllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo *pAllocateInfo, 6615bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDescriptorSet *pDescriptorSets) { 661656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 6617b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 66187f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlis cvdescriptorset::AllocateDescriptorSetsData common_data(pAllocateInfo->descriptorSetCount); 66197f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlis bool skip_call = PreCallValidateAllocateDescriptorSets(dev_data, pAllocateInfo, &common_data); 6620b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 6621d173e0daab123373ce75105f2a908f6ae7cef6abChris Forbes 6622cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip_call) return VK_ERROR_VALIDATION_FAILED_EXT; 6623d173e0daab123373ce75105f2a908f6ae7cef6abChris Forbes 66244a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.AllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets); 66256511ce241f7f210211e0c0e882f3c14889071f4dChris Forbes 66265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 6627b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.lock(); 66287f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlis PostCallRecordAllocateDescriptorSets(dev_data, pAllocateInfo, pDescriptorSets, &common_data); 6629b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 66305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 66315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 66325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 6633cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis// Verify state before freeing DescriptorSets 6634cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlisstatic bool PreCallValidateFreeDescriptorSets(const layer_data *dev_data, VkDescriptorPool pool, uint32_t count, 6635cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis const VkDescriptorSet *descriptor_sets) { 6636cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.free_descriptor_sets) return false; 6637cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis bool skip_call = false; 6638cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis // First make sure sets being destroyed are not currently in-use 6639405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour for (uint32_t i = 0; i < count; ++i) { 6640405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (descriptor_sets[i] != VK_NULL_HANDLE) { 6641405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour skip_call |= validateIdleDescriptorSet(dev_data, descriptor_sets[i], "vkFreeDescriptorSets"); 6642405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 6643405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 6644cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis 66459a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DESCRIPTOR_POOL_STATE *pool_state = GetDescriptorPoolState(dev_data, pool); 6646a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis if (pool_state && !(VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT & pool_state->createInfo.flags)) { 6647cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis // Can't Free from a NON_FREE pool 6648cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, 66491c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis reinterpret_cast<uint64_t &>(pool), __LINE__, VALIDATION_ERROR_00922, "DS", 6650cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis "It is invalid to call vkFreeDescriptorSets() with a pool created without setting " 66511c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis "VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT. %s", 66521c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis validation_error_map[VALIDATION_ERROR_00922]); 6653cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis } 6654cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis return skip_call; 6655cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis} 6656cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis// Sets have been removed from the pool so update underlying state 6657cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlisstatic void PostCallRecordFreeDescriptorSets(layer_data *dev_data, VkDescriptorPool pool, uint32_t count, 6658cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis const VkDescriptorSet *descriptor_sets) { 66599a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DESCRIPTOR_POOL_STATE *pool_state = GetDescriptorPoolState(dev_data, pool); 6660cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis // Update available descriptor sets in pool 6661cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis pool_state->availableSets += count; 6662cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis 6663cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis // For each freed descriptor add its resources back into the pool as available and remove from pool and setMap 6664cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis for (uint32_t i = 0; i < count; ++i) { 6665405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (descriptor_sets[i] != VK_NULL_HANDLE) { 6666405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour auto descriptor_set = dev_data->setMap[descriptor_sets[i]]; 6667405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour uint32_t type_index = 0, descriptor_count = 0; 6668405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour for (uint32_t j = 0; j < descriptor_set->GetBindingCount(); ++j) { 6669405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour type_index = static_cast<uint32_t>(descriptor_set->GetTypeFromIndex(j)); 6670405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour descriptor_count = descriptor_set->GetDescriptorCountFromIndex(j); 6671405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour pool_state->availableDescriptorTypeCount[type_index] += descriptor_count; 6672405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 6673405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour freeDescriptorSet(dev_data, descriptor_set); 6674405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour pool_state->sets.erase(descriptor_set); 6675405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 6676cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis } 6677cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis} 66785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6679bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL FreeDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool, uint32_t count, 6680bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkDescriptorSet *pDescriptorSets) { 668156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 66825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Make sure that no sets being destroyed are in-flight 6683b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 668483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = PreCallValidateFreeDescriptorSets(dev_data, descriptorPool, count, pDescriptorSets); 6685b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 6686e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis 6687cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip_call) return VK_ERROR_VALIDATION_FAILED_EXT; 66884a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.FreeDescriptorSets(device, descriptorPool, count, pDescriptorSets); 66895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 6690b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.lock(); 6691cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis PostCallRecordFreeDescriptorSets(dev_data, descriptorPool, count, pDescriptorSets); 6692b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 66935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 66945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 66955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 66966b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis// TODO : This is a Proof-of-concept for core validation architecture 66976b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis// Really we'll want to break out these functions to separate files but 66986b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis// keeping it all together here to prove out design 66996b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis// PreCallValidate* handles validating all of the state prior to calling down chain to UpdateDescriptorSets() 67006b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlisstatic bool PreCallValidateUpdateDescriptorSets(layer_data *dev_data, uint32_t descriptorWriteCount, 67016b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis const VkWriteDescriptorSet *pDescriptorWrites, uint32_t descriptorCopyCount, 67026b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis const VkCopyDescriptorSet *pDescriptorCopies) { 6703cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.update_descriptor_sets) return false; 67046b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis // First thing to do is perform map look-ups. 67056b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis // NOTE : UpdateDescriptorSets is somewhat unique in that it's operating on a number of DescriptorSets 67066b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis // so we can't just do a single map look-up up-front, but do them individually in functions below 67076b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis 67086b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis // Now make call(s) that validate state, but don't perform state updates in this function 67096b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis // Note, here DescriptorSets is unique in that we don't yet have an instance. Using a helper function in the 67106b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis // namespace which will parse params and make calls into specific class instances 6711104ab082916e41467ef60baaab7a5a8b2e02c59cTobin Ehlis return cvdescriptorset::ValidateUpdateDescriptorSets(dev_data->report_data, dev_data, descriptorWriteCount, pDescriptorWrites, 6712104ab082916e41467ef60baaab7a5a8b2e02c59cTobin Ehlis descriptorCopyCount, pDescriptorCopies); 67136b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis} 67146b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis// PostCallRecord* handles recording state updates following call down chain to UpdateDescriptorSets() 67156b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlisstatic void PostCallRecordUpdateDescriptorSets(layer_data *dev_data, uint32_t descriptorWriteCount, 67166b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis const VkWriteDescriptorSet *pDescriptorWrites, uint32_t descriptorCopyCount, 67176b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis const VkCopyDescriptorSet *pDescriptorCopies) { 6718104ab082916e41467ef60baaab7a5a8b2e02c59cTobin Ehlis cvdescriptorset::PerformUpdateDescriptorSets(dev_data, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, 67196b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis pDescriptorCopies); 67206b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis} 67215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6722bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL UpdateDescriptorSets(VkDevice device, uint32_t descriptorWriteCount, 6723bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkWriteDescriptorSet *pDescriptorWrites, uint32_t descriptorCopyCount, 6724bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkCopyDescriptorSet *pDescriptorCopies) { 67256b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis // Only map look-up at top level is for device-level layer_data 672656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 6727b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 67286b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis bool skip_call = PreCallValidateUpdateDescriptorSets(dev_data, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, 67296b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis pDescriptorCopies); 6730b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 67316b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis if (!skip_call) { 67324a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.UpdateDescriptorSets(device, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, 67334a0754042cf090e131e9e769d8a3633c228625beChris Forbes pDescriptorCopies); 67346b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis lock.lock(); 67356b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis // Since UpdateDescriptorSets() is void, nothing to check prior to updating state 67366b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis PostCallRecordUpdateDescriptorSets(dev_data, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, 67376b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis pDescriptorCopies); 67385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 67395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 67405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6741bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL AllocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo *pCreateInfo, 6742bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkCommandBuffer *pCommandBuffer) { 674356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 67444a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.AllocateCommandBuffers(device, pCreateInfo, pCommandBuffer); 67455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 6746b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 67479a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pPool = GetCommandPoolNode(dev_data, pCreateInfo->commandPool); 6748cd9a648074f67a1d44c15a056b90fc66da8ead17Chris Forbes 6749cd9a648074f67a1d44c15a056b90fc66da8ead17Chris Forbes if (pPool) { 675072d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis for (uint32_t i = 0; i < pCreateInfo->commandBufferCount; i++) { 67515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Add command buffer to its commandPool map 6752cd9a648074f67a1d44c15a056b90fc66da8ead17Chris Forbes pPool->commandBuffers.push_back(pCommandBuffer[i]); 67535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis GLOBAL_CB_NODE *pCB = new GLOBAL_CB_NODE; 67545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Add command buffer to map 67555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->commandBufferMap[pCommandBuffer[i]] = pCB; 67565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis resetCB(dev_data, pCommandBuffer[i]); 67575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->createInfo = *pCreateInfo; 67585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->device = device; 67595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 67605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6761b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 67625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 67635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 67645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 67655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6766883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis// Add bindings between the given cmd buffer & framebuffer and the framebuffer's children 6767c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlisstatic void AddFramebufferBinding(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, FRAMEBUFFER_STATE *fb_state) { 67680245b74a083d2cb3b083571deb0fe13b4ab428a4Tobin Ehlis addCommandBufferBinding(&fb_state->cb_bindings, 67690245b74a083d2cb3b083571deb0fe13b4ab428a4Tobin Ehlis {reinterpret_cast<uint64_t &>(fb_state->framebuffer), VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT}, 67700245b74a083d2cb3b083571deb0fe13b4ab428a4Tobin Ehlis cb_state); 6771883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis for (auto attachment : fb_state->attachments) { 6772883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis auto view_state = attachment.view_state; 6773883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis if (view_state) { 677403ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis AddCommandBufferBindingImageView(dev_data, cb_state, view_state); 6775883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis } 67769a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto rp_state = GetRenderPassState(dev_data, fb_state->createInfo.renderPass); 6777883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis if (rp_state) { 6778883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis addCommandBufferBinding( 6779883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis &rp_state->cb_bindings, 6780883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis {reinterpret_cast<uint64_t &>(rp_state->renderPass), VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT}, cb_state); 6781883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis } 6782883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis } 6783883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis} 6784883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis 6785bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL BeginCommandBuffer(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo *pBeginInfo) { 678683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 678756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 6788b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 67895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Validate command buffer level 67909a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *cb_node = GetCBNode(dev_data, commandBuffer); 6791f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis if (cb_node) { 67925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // This implicitly resets the Cmd Buffer so make sure any fence is done and then clear memory references 6793a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis if (dev_data->globalInFlightCmdBuffers.count(commandBuffer)) { 679483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= 6795a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 67964527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton (uint64_t)commandBuffer, __LINE__, VALIDATION_ERROR_00104, "MEM", 6797d79335137b414d5f89284a9ab3e014beb4ada3ebMike Weiblen "Calling vkBeginCommandBuffer() on active command buffer 0x%p before it has completed. " 67984527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton "You must check command buffer fence before this call. %s", 67994527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton commandBuffer, validation_error_map[VALIDATION_ERROR_00104]); 68005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6801f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis clear_cmd_buf_and_mem_references(dev_data, cb_node); 6802f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis if (cb_node->createInfo.level != VK_COMMAND_BUFFER_LEVEL_PRIMARY) { 68035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Secondary Command Buffer 68045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkCommandBufferInheritanceInfo *pInfo = pBeginInfo->pInheritanceInfo; 68055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!pInfo) { 680683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= 68075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 68084527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton reinterpret_cast<uint64_t>(commandBuffer), __LINE__, VALIDATION_ERROR_00106, "DS", 6809bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "vkBeginCommandBuffer(): Secondary Command Buffer (0x%p) must have inheritance info. %s", commandBuffer, 6810bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski validation_error_map[VALIDATION_ERROR_00106]); 68115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 68125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pBeginInfo->flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT) { 68132c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis // Object_tracker makes sure these objects are valid 68142c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis assert(pInfo->renderPass); 68152c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis assert(pInfo->framebuffer); 68162c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis string errorString = ""; 68179a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto framebuffer = GetFramebufferState(dev_data, pInfo->framebuffer); 68182c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis if (framebuffer) { 68192c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis if ((framebuffer->createInfo.renderPass != pInfo->renderPass) && 68202c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis !verify_renderpass_compatibility(dev_data, framebuffer->renderPassCreateInfo.ptr(), 68219a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GetRenderPassState(dev_data, pInfo->renderPass)->createInfo.ptr(), 68222c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis errorString)) { 68232c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis // renderPass that framebuffer was created with must be compatible with local renderPass 68242c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 68252c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 68262c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis reinterpret_cast<uint64_t>(commandBuffer), __LINE__, VALIDATION_ERROR_00112, "DS", 68272c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis "vkBeginCommandBuffer(): Secondary Command " 6828cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Buffer (0x%p) renderPass (0x%" PRIxLEAST64 6829cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ") is incompatible w/ framebuffer " 68302c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis "(0x%" PRIxLEAST64 ") w/ render pass (0x%" PRIxLEAST64 ") due to: %s. %s", 68312c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis commandBuffer, reinterpret_cast<const uint64_t &>(pInfo->renderPass), 68322c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis reinterpret_cast<const uint64_t &>(pInfo->framebuffer), 68332c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis reinterpret_cast<uint64_t &>(framebuffer->createInfo.renderPass), 68342c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis errorString.c_str(), validation_error_map[VALIDATION_ERROR_00112]); 68355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 68362c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis // Connect this framebuffer and its children to this cmdBuffer 68372c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis AddFramebufferBinding(dev_data, cb_node, framebuffer); 68385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 68395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 68404527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton if ((pInfo->occlusionQueryEnable == VK_FALSE || dev_data->enabled_features.occlusionQueryPrecise == VK_FALSE) && 68415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (pInfo->queryFlags & VK_QUERY_CONTROL_PRECISE_BIT)) { 684283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 684383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t>(commandBuffer), 68444527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton __LINE__, VALIDATION_ERROR_00107, "DS", 684583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis "vkBeginCommandBuffer(): Secondary Command Buffer (0x%p) must not have " 684683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis "VK_QUERY_CONTROL_PRECISE_BIT if occulusionQuery is disabled or the device does not " 68474527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton "support precise occlusion queries. %s", 68484527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton commandBuffer, validation_error_map[VALIDATION_ERROR_00107]); 68495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 68505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 68515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pInfo && pInfo->renderPass != VK_NULL_HANDLE) { 68529a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto renderPass = GetRenderPassState(dev_data, pInfo->renderPass); 685316387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes if (renderPass) { 6854fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes if (pInfo->subpass >= renderPass->createInfo.subpassCount) { 685583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg( 6856bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 6857bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski (uint64_t)commandBuffer, __LINE__, VALIDATION_ERROR_00111, "DS", 68584527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton "vkBeginCommandBuffer(): Secondary Command Buffers (0x%p) must have a subpass index (%d) " 68594527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton "that is less than the number of subpasses (%d). %s", 68604527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton commandBuffer, pInfo->subpass, renderPass->createInfo.subpassCount, 68614527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton validation_error_map[VALIDATION_ERROR_00111]); 68625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 68635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 68645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 68655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6866f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis if (CB_RECORDING == cb_node->state) { 6867cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski skip_call |= 6868cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 6869cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski (uint64_t)commandBuffer, __LINE__, VALIDATION_ERROR_00103, "DS", 6870cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkBeginCommandBuffer(): Cannot call Begin on command buffer (0x%p" 6871cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ") in the RECORDING state. Must first call vkEndCommandBuffer(). %s", 6872cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski commandBuffer, validation_error_map[VALIDATION_ERROR_00103]); 6873347d4d3139a1e743ed85bd375c20fd35bbe68d74Chris Forbes } else if (CB_RECORDED == cb_node->state || (CB_INVALID == cb_node->state && CMD_END == cb_node->last_cmd)) { 6874f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis VkCommandPool cmdPool = cb_node->createInfo.commandPool; 68759a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pPool = GetCommandPoolNode(dev_data, cmdPool); 6876cd9a648074f67a1d44c15a056b90fc66da8ead17Chris Forbes if (!(VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT & pPool->createFlags)) { 687783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= 68785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 68794527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton (uint64_t)commandBuffer, __LINE__, VALIDATION_ERROR_00105, "DS", 6880226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "Call to vkBeginCommandBuffer() on command buffer (0x%p" 6881414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller ") attempts to implicitly reset cmdBuffer created from command pool (0x%" PRIxLEAST64 68824527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton ") that does NOT have the VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT bit set. %s", 68834527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton commandBuffer, (uint64_t)cmdPool, validation_error_map[VALIDATION_ERROR_00105]); 68845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 68855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis resetCB(dev_data, commandBuffer); 68865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 68875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Set updated state here in case implicit reset occurs above 6888f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->state = CB_RECORDING; 6889f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->beginInfo = *pBeginInfo; 6890f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis if (cb_node->beginInfo.pInheritanceInfo) { 6891f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->inheritanceInfo = *(cb_node->beginInfo.pInheritanceInfo); 6892f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->beginInfo.pInheritanceInfo = &cb_node->inheritanceInfo; 6893888e1d268098177fde4a2263e3d7b7cc415f1debMark Young // If we are a secondary command-buffer and inheriting. Update the items we should inherit. 6894f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis if ((cb_node->createInfo.level != VK_COMMAND_BUFFER_LEVEL_PRIMARY) && 6895f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis (cb_node->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT)) { 68969a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis cb_node->activeRenderPass = GetRenderPassState(dev_data, cb_node->beginInfo.pInheritanceInfo->renderPass); 6897f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->activeSubpass = cb_node->beginInfo.pInheritanceInfo->subpass; 6898350841afb70bf8dcfc3c6ec6b66f0aaa639553a3Tobin Ehlis cb_node->activeFramebuffer = cb_node->beginInfo.pInheritanceInfo->framebuffer; 6899f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->framebuffers.insert(cb_node->beginInfo.pInheritanceInfo->framebuffer); 6900888e1d268098177fde4a2263e3d7b7cc415f1debMark Young } 69015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 69025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6903b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 690483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis if (skip_call) { 69055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return VK_ERROR_VALIDATION_FAILED_EXT; 69065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 69074a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.BeginCommandBuffer(commandBuffer, pBeginInfo); 6908400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis 69095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 69105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 69115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 691289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL EndCommandBuffer(VkCommandBuffer commandBuffer) { 691383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 69145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkResult result = VK_SUCCESS; 691556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 6916b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 69179a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 69185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 69194527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton if ((VK_COMMAND_BUFFER_LEVEL_PRIMARY == pCB->createInfo.level) || 69204527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton !(pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT)) { 6921fd61966f8d41b5bce15620b70563b7864cbb28feCody Northrop // This needs spec clarification to update valid usage, see comments in PR: 6922fd61966f8d41b5bce15620b70563b7864cbb28feCody Northrop // https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/pull/516#discussion_r63013756 6923ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen skip_call |= insideRenderPass(dev_data, pCB, "vkEndCommandBuffer()", VALIDATION_ERROR_00123); 6924fd61966f8d41b5bce15620b70563b7864cbb28feCody Northrop } 692529f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_END, "vkEndCommandBuffer()"); 69261ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_END); 69275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto query : pCB->activeQueries) { 692883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 69294527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton VALIDATION_ERROR_00124, "DS", 69304527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton "Ending command buffer with in progress query: queryPool 0x%" PRIx64 ", index %d. %s", 69314527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton (uint64_t)(query.pool), query.index, validation_error_map[VALIDATION_ERROR_00124]); 69325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 69335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 693483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis if (!skip_call) { 6935b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 69364a0754042cf090e131e9e769d8a3633c228625beChris Forbes result = dev_data->dispatch_table.EndCommandBuffer(commandBuffer); 6937b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.lock(); 69385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 69395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->state = CB_RECORDED; 69405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Reset CB status flags 69415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->status = 0; 69425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 69435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 69445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis result = VK_ERROR_VALIDATION_FAILED_EXT; 69455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6946b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 69475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 69485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 69495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6950bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL ResetCommandBuffer(VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags) { 6951bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis bool skip_call = false; 695256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 6953b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 69549a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 69555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkCommandPool cmdPool = pCB->createInfo.commandPool; 69569a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pPool = GetCommandPoolNode(dev_data, cmdPool); 6957cd9a648074f67a1d44c15a056b90fc66da8ead17Chris Forbes if (!(VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT & pPool->createFlags)) { 6958bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 69594527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton (uint64_t)commandBuffer, __LINE__, VALIDATION_ERROR_00093, "DS", 6960226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "Attempt to reset command buffer (0x%p) created from command pool (0x%" PRIxLEAST64 69614527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton ") that does NOT have the VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT bit set. %s", 69624527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton commandBuffer, (uint64_t)cmdPool, validation_error_map[VALIDATION_ERROR_00093]); 69635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6964cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlis skip_call |= checkCommandBufferInFlight(dev_data, pCB, "reset", VALIDATION_ERROR_00092); 6965b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 6966cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip_call) return VK_ERROR_VALIDATION_FAILED_EXT; 69674a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.ResetCommandBuffer(commandBuffer, flags); 69685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 6969b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.lock(); 6970a964cad279f9749cd9ebfc7555247ff3bff26d53Chris Forbes dev_data->globalInFlightCmdBuffers.erase(commandBuffer); 69715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis resetCB(dev_data, commandBuffer); 6972b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 69735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 69745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 69755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 697693c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski 6977bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBindPipeline(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, 6978bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkPipeline pipeline) { 6979e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis bool skip = false; 698056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 6981b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 69829a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer); 6983e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis if (cb_state) { 698429f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip |= ValidateCmd(dev_data, cb_state, CMD_BINDPIPELINE, "vkCmdBindPipeline()"); 69851ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(cb_state, CMD_BINDPIPELINE); 6986e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis if ((VK_PIPELINE_BIND_POINT_COMPUTE == pipelineBindPoint) && (cb_state->activeRenderPass)) { 6987e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis skip |= 69885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 69895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (uint64_t)pipeline, __LINE__, DRAWSTATE_INVALID_RENDERPASS_CMD, "DS", 6990414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller "Incorrectly binding compute pipeline (0x%" PRIxLEAST64 ") during active RenderPass (0x%" PRIxLEAST64 ")", 6991e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis (uint64_t)pipeline, (uint64_t)cb_state->activeRenderPass->renderPass); 69925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 69934527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton // TODO: VALIDATION_ERROR_00594 VALIDATION_ERROR_00596 69945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6995e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis PIPELINE_STATE *pipe_state = getPipelineState(dev_data, pipeline); 6996e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis if (pipe_state) { 6997e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis cb_state->lastBound[pipelineBindPoint].pipeline_state = pipe_state; 6998e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis set_cb_pso_status(cb_state, pipe_state); 6999e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis set_pipeline_state(pipe_state); 70005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 7001e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 70024527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton (uint64_t)pipeline, __LINE__, VALIDATION_ERROR_00600, "DS", 70034527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton "Attempt to bind Pipeline 0x%" PRIxLEAST64 " that doesn't exist! %s", (uint64_t)(pipeline), 70044527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton validation_error_map[VALIDATION_ERROR_00600]); 7005e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis } 7006e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis addCommandBufferBinding(&pipe_state->cb_bindings, 7007e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis {reinterpret_cast<uint64_t &>(pipeline), VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT}, cb_state); 7008e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis if (VK_PIPELINE_BIND_POINT_GRAPHICS == pipelineBindPoint) { 7009e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis // Add binding for child renderpass 70109a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto rp_state = GetRenderPassState(dev_data, pipe_state->graphicsPipelineCI.renderPass); 7011e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis if (rp_state) { 7012e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis addCommandBufferBinding( 7013e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis &rp_state->cb_bindings, 7014e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis {reinterpret_cast<uint64_t &>(rp_state->renderPass), VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT}, cb_state); 7015e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis } 70165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 70175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7018b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7019cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdBindPipeline(commandBuffer, pipelineBindPoint, pipeline); 70205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 70215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7022bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetViewport(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, 7023bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkViewport *pViewports) { 702483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 702556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7026b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 70279a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 70285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 702929f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_SETVIEWPORTSTATE, "vkCmdSetViewport()"); 70301ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETVIEWPORTSTATE); 7031bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pCB->viewportMask |= ((1u << viewportCount) - 1u) << firstViewport; 70325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7033b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7034cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.CmdSetViewport(commandBuffer, firstViewport, viewportCount, pViewports); 70355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 70365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7037bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetScissor(VkCommandBuffer commandBuffer, uint32_t firstScissor, uint32_t scissorCount, 7038bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkRect2D *pScissors) { 703983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 704056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7041b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 70429a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 70435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 704429f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_SETSCISSORSTATE, "vkCmdSetScissor()"); 70451ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETSCISSORSTATE); 7046bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pCB->scissorMask |= ((1u << scissorCount) - 1u) << firstScissor; 70475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7048b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7049cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.CmdSetScissor(commandBuffer, firstScissor, scissorCount, pScissors); 70505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 70515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 705289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdSetLineWidth(VkCommandBuffer commandBuffer, float lineWidth) { 7053a27508babf63d50aea75883a3702979193c23683Mark Young bool skip_call = false; 705456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7055b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 70569a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 70575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 705829f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_SETLINEWIDTHSTATE, "vkCmdSetLineWidth()"); 70591ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETLINEWIDTHSTATE); 70605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->status |= CBSTATUS_LINE_WIDTH_SET; 7061a27508babf63d50aea75883a3702979193c23683Mark Young 70624c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis PIPELINE_STATE *pPipeTrav = pCB->lastBound[VK_PIPELINE_BIND_POINT_GRAPHICS].pipeline_state; 7063a27508babf63d50aea75883a3702979193c23683Mark Young if (pPipeTrav != NULL && !isDynamic(pPipeTrav, VK_DYNAMIC_STATE_LINE_WIDTH)) { 7064a27508babf63d50aea75883a3702979193c23683Mark Young skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 706555eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen reinterpret_cast<uint64_t &>(commandBuffer), __LINE__, VALIDATION_ERROR_01476, "DS", 7066386d9a9a77f884789a7ae4c3890aecd47132f2babaldurk "vkCmdSetLineWidth called but pipeline was created without VK_DYNAMIC_STATE_LINE_WIDTH " 706755eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen "flag. This is undefined behavior and could be ignored. %s", 706855eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen validation_error_map[VALIDATION_ERROR_01476]); 7069a27508babf63d50aea75883a3702979193c23683Mark Young } else { 7070a27508babf63d50aea75883a3702979193c23683Mark Young skip_call |= verifyLineWidth(dev_data, DRAWSTATE_INVALID_SET, reinterpret_cast<uint64_t &>(commandBuffer), lineWidth); 7071a27508babf63d50aea75883a3702979193c23683Mark Young } 70725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7073b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7074cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.CmdSetLineWidth(commandBuffer, lineWidth); 70755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 70765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7077bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetDepthBias(VkCommandBuffer commandBuffer, float depthBiasConstantFactor, float depthBiasClamp, 7078bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski float depthBiasSlopeFactor) { 707983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 708056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7081b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 70829a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 70835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 708429f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_SETDEPTHBIASSTATE, "vkCmdSetDepthBias()"); 70851ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETDEPTHBIASSTATE); 70865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->status |= CBSTATUS_DEPTH_BIAS_SET; 70875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7088b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 708983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis if (!skip_call) 70904a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdSetDepthBias(commandBuffer, depthBiasConstantFactor, depthBiasClamp, depthBiasSlopeFactor); 70915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 70925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 709389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdSetBlendConstants(VkCommandBuffer commandBuffer, const float blendConstants[4]) { 709483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 709556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7096b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 70979a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 70985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 709929f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_SETBLENDSTATE, "vkCmdSetBlendConstants()"); 71001ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETBLENDSTATE); 71013d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis pCB->status |= CBSTATUS_BLEND_CONSTANTS_SET; 71025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7103b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7104cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.CmdSetBlendConstants(commandBuffer, blendConstants); 71055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 71065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7107bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetDepthBounds(VkCommandBuffer commandBuffer, float minDepthBounds, float maxDepthBounds) { 710883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 710956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7110b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 71119a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 71125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 711329f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_SETDEPTHBOUNDSSTATE, "vkCmdSetDepthBounds()"); 71141ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETDEPTHBOUNDSSTATE); 71155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->status |= CBSTATUS_DEPTH_BOUNDS_SET; 71165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7117b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7118cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.CmdSetDepthBounds(commandBuffer, minDepthBounds, maxDepthBounds); 71195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 71205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7121bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetStencilCompareMask(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, 7122bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski uint32_t compareMask) { 712383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 712456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7125b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 71269a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 71275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 712829f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_SETSTENCILREADMASKSTATE, "vkCmdSetStencilCompareMask()"); 71291ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETSTENCILREADMASKSTATE); 71305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->status |= CBSTATUS_STENCIL_READ_MASK_SET; 71315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7132b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7133cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.CmdSetStencilCompareMask(commandBuffer, faceMask, compareMask); 71345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 71355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7136bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetStencilWriteMask(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t writeMask) { 713783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 713856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7139b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 71409a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 71415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 714229f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_SETSTENCILWRITEMASKSTATE, "vkCmdSetStencilWriteMask()"); 71431ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETSTENCILWRITEMASKSTATE); 71445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->status |= CBSTATUS_STENCIL_WRITE_MASK_SET; 71455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7146b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7147cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.CmdSetStencilWriteMask(commandBuffer, faceMask, writeMask); 71485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 71495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7150bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetStencilReference(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t reference) { 715183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 715256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7153b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 71549a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 71555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 715629f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_SETSTENCILREFERENCESTATE, "vkCmdSetStencilReference()"); 71571ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETSTENCILREFERENCESTATE); 71585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->status |= CBSTATUS_STENCIL_REFERENCE_SET; 71595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7160b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7161cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.CmdSetStencilReference(commandBuffer, faceMask, reference); 71625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 71635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7164bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBindDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, 7165bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkPipelineLayout layout, uint32_t firstSet, uint32_t setCount, 7166bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkDescriptorSet *pDescriptorSets, uint32_t dynamicOffsetCount, 7167bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const uint32_t *pDynamicOffsets) { 7168946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski bool skip = false; 716956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7170b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7171946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer); 7172946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (cb_state) { 7173946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ValidateCmd(dev_data, cb_state, CMD_BINDDESCRIPTORSETS, "vkCmdBindDescriptorSets()"); 7174ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski // Track total count of dynamic descriptor types to make sure we have an offset for each one 7175946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski uint32_t total_dynamic_descriptors = 0; 7176946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski string error_string = ""; 7177946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski uint32_t last_set_index = firstSet + setCount - 1; 7178946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (last_set_index >= cb_state->lastBound[pipelineBindPoint].boundDescriptorSets.size()) { 7179946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->lastBound[pipelineBindPoint].boundDescriptorSets.resize(last_set_index + 1); 7180946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->lastBound[pipelineBindPoint].dynamicOffsets.resize(last_set_index + 1); 7181946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski } 7182946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski auto old_final_bound_set = cb_state->lastBound[pipelineBindPoint].boundDescriptorSets[last_set_index]; 7183ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski auto pipeline_layout = getPipelineLayout(dev_data, layout); 7184ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski for (uint32_t set_idx = 0; set_idx < setCount; set_idx++) { 7185ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski cvdescriptorset::DescriptorSet *descriptor_set = GetSetNode(dev_data, pDescriptorSets[set_idx]); 7186ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski if (descriptor_set) { 7187946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->lastBound[pipelineBindPoint].pipeline_layout = *pipeline_layout; 7188946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->lastBound[pipelineBindPoint].boundDescriptorSets[set_idx + firstSet] = descriptor_set; 7189946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 7190946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t)pDescriptorSets[set_idx], __LINE__, 7191946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski DRAWSTATE_NONE, "DS", "Descriptor Set 0x%" PRIxLEAST64 " bound on pipeline %s", 7192946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski (uint64_t)pDescriptorSets[set_idx], string_VkPipelineBindPoint(pipelineBindPoint)); 7193ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski if (!descriptor_set->IsUpdated() && (descriptor_set->GetTotalDescriptorCount() != 0)) { 7194946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, 7195946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t)pDescriptorSets[set_idx], __LINE__, 7196946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski DRAWSTATE_DESCRIPTOR_SET_NOT_UPDATED, "DS", 7197946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "Descriptor Set 0x%" PRIxLEAST64 7198946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski " bound but it was never updated. You may want to either update it or not bind it.", 7199946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski (uint64_t)pDescriptorSets[set_idx]); 7200ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } 7201ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski // Verify that set being bound is compatible with overlapping setLayout of pipelineLayout 7202946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (!verify_set_layout_compatibility(dev_data, descriptor_set, pipeline_layout, set_idx + firstSet, error_string)) { 7203946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 7204946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t)pDescriptorSets[set_idx], __LINE__, 7205946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski VALIDATION_ERROR_00974, "DS", 7206946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "descriptorSet #%u being bound is not compatible with overlapping descriptorSetLayout " 7207946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "at index %u of pipelineLayout 0x%" PRIxLEAST64 " due to: %s. %s", 7208946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski set_idx, set_idx + firstSet, reinterpret_cast<uint64_t &>(layout), error_string.c_str(), 7209946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski validation_error_map[VALIDATION_ERROR_00974]); 72105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7211ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski 7212946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski auto set_dynamic_descriptor_count = descriptor_set->GetDynamicDescriptorCount(); 7213ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski 7214946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->lastBound[pipelineBindPoint].dynamicOffsets[firstSet + set_idx].clear(); 7215ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski 7216946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (set_dynamic_descriptor_count) { 7217ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski // First make sure we won't overstep bounds of pDynamicOffsets array 7218946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if ((total_dynamic_descriptors + set_dynamic_descriptor_count) > dynamicOffsetCount) { 7219946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 7220946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t)pDescriptorSets[set_idx], 7221946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski __LINE__, DRAWSTATE_INVALID_DYNAMIC_OFFSET_COUNT, "DS", 7222946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "descriptorSet #%u (0x%" PRIxLEAST64 7223946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski ") requires %u dynamicOffsets, but only %u dynamicOffsets are left in pDynamicOffsets " 7224946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "array. There must be one dynamic offset for each dynamic descriptor being bound.", 7225946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski set_idx, (uint64_t)pDescriptorSets[set_idx], descriptor_set->GetDynamicDescriptorCount(), 7226946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski (dynamicOffsetCount - total_dynamic_descriptors)); 7227ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } else { // Validate and store dynamic offsets with the set 7228ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski // Validate Dynamic Offset Minimums 7229946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski uint32_t cur_dyn_offset = total_dynamic_descriptors; 7230ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski for (uint32_t d = 0; d < descriptor_set->GetTotalDescriptorCount(); d++) { 7231ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski if (descriptor_set->GetTypeFromGlobalIndex(d) == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) { 7232ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski if (vk_safe_modulo( 7233ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski pDynamicOffsets[cur_dyn_offset], 7234ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski dev_data->phys_dev_properties.properties.limits.minUniformBufferOffsetAlignment) != 0) { 7235946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= log_msg( 7236ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 7237ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, VALIDATION_ERROR_00978, "DS", 7238ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski "vkCmdBindDescriptorSets(): pDynamicOffsets[%d] is %d but must be a multiple of " 7239ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski "device limit minUniformBufferOffsetAlignment 0x%" PRIxLEAST64 ". %s", 7240ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski cur_dyn_offset, pDynamicOffsets[cur_dyn_offset], 7241ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski dev_data->phys_dev_properties.properties.limits.minUniformBufferOffsetAlignment, 7242ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski validation_error_map[VALIDATION_ERROR_00978]); 7243ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } 7244ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski cur_dyn_offset++; 7245ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } else if (descriptor_set->GetTypeFromGlobalIndex(d) == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) { 7246ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski if (vk_safe_modulo( 7247ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski pDynamicOffsets[cur_dyn_offset], 7248ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski dev_data->phys_dev_properties.properties.limits.minStorageBufferOffsetAlignment) != 0) { 7249946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= log_msg( 7250ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 7251ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, VALIDATION_ERROR_00978, "DS", 7252ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski "vkCmdBindDescriptorSets(): pDynamicOffsets[%d] is %d but must be a multiple of " 7253ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski "device limit minStorageBufferOffsetAlignment 0x%" PRIxLEAST64 ". %s", 7254ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski cur_dyn_offset, pDynamicOffsets[cur_dyn_offset], 7255ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski dev_data->phys_dev_properties.properties.limits.minStorageBufferOffsetAlignment, 7256ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski validation_error_map[VALIDATION_ERROR_00978]); 7257ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } 7258ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski cur_dyn_offset++; 7259ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } 726072d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis } 7261ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski 7262946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->lastBound[pipelineBindPoint].dynamicOffsets[firstSet + set_idx] = 7263946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski std::vector<uint32_t>(pDynamicOffsets + total_dynamic_descriptors, 7264946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski pDynamicOffsets + total_dynamic_descriptors + set_dynamic_descriptor_count); 7265ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski // Keep running total of dynamic descriptor count to verify at the end 7266946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski total_dynamic_descriptors += set_dynamic_descriptor_count; 726772d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis } 726872d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis } 7269ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } else { 7270946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= log_msg( 7271ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, 7272ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski (uint64_t)pDescriptorSets[set_idx], __LINE__, DRAWSTATE_INVALID_SET, "DS", 7273ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski "Attempt to bind descriptor set 0x%" PRIxLEAST64 " that doesn't exist!", (uint64_t)pDescriptorSets[set_idx]); 7274ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } 7275946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski UpdateCmdBufferLastCmd(cb_state, CMD_BINDDESCRIPTORSETS); 7276ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski // For any previously bound sets, need to set them to "invalid" if they were disturbed by this update 7277ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski if (firstSet > 0) { // Check set #s below the first bound set 7278ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski for (uint32_t i = 0; i < firstSet; ++i) { 7279946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (cb_state->lastBound[pipelineBindPoint].boundDescriptorSets[i] && 7280946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski !verify_set_layout_compatibility(dev_data, cb_state->lastBound[pipelineBindPoint].boundDescriptorSets[i], 7281946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski pipeline_layout, i, error_string)) { 7282946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= log_msg( 7283ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, 7284ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, 7285946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski (uint64_t)cb_state->lastBound[pipelineBindPoint].boundDescriptorSets[i], __LINE__, DRAWSTATE_NONE, "DS", 7286ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski "DescriptorSet 0x%" PRIxLEAST64 7287ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski " previously bound as set #%u was disturbed by newly bound pipelineLayout (0x%" PRIxLEAST64 ")", 7288946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski (uint64_t)cb_state->lastBound[pipelineBindPoint].boundDescriptorSets[i], i, (uint64_t)layout); 7289946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->lastBound[pipelineBindPoint].boundDescriptorSets[i] = VK_NULL_HANDLE; 72905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 72915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 72925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7293ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski // Check if newly last bound set invalidates any remaining bound sets 7294946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if ((cb_state->lastBound[pipelineBindPoint].boundDescriptorSets.size() - 1) > (last_set_index)) { 7295946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (old_final_bound_set && 7296946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski !verify_set_layout_compatibility(dev_data, old_final_bound_set, pipeline_layout, last_set_index, 7297946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski error_string)) { 7298946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski auto old_set = old_final_bound_set->GetSet(); 7299946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, 7300946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, reinterpret_cast<uint64_t &>(old_set), __LINE__, 7301946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski DRAWSTATE_NONE, "DS", "DescriptorSet 0x%" PRIxLEAST64 7302946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski " previously bound as set #%u is incompatible with set 0x%" PRIxLEAST64 7303946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski " newly bound as set #%u so set #%u and any subsequent sets were " 7304946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "disturbed by newly bound pipelineLayout (0x%" PRIxLEAST64 ")", 7305946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski reinterpret_cast<uint64_t &>(old_set), last_set_index, 7306946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski (uint64_t)cb_state->lastBound[pipelineBindPoint].boundDescriptorSets[last_set_index], 7307946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski last_set_index, last_set_index + 1, (uint64_t)layout); 7308946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->lastBound[pipelineBindPoint].boundDescriptorSets.resize(last_set_index + 1); 7309ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } 7310787f29d93dee194c015789cf61c079504c980572Tobin Ehlis } 7311ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } 7312ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski // dynamicOffsetCount must equal the total number of dynamic descriptors in the sets being bound 7313946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (total_dynamic_descriptors != dynamicOffsetCount) { 7314946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 7315946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski (uint64_t)commandBuffer, __LINE__, VALIDATION_ERROR_00975, "DS", 7316946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "Attempting to bind %u descriptorSets with %u dynamic descriptors, but dynamicOffsetCount " 7317946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "is %u. It should exactly match the number of dynamic descriptors. %s", 7318946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski setCount, total_dynamic_descriptors, dynamicOffsetCount, validation_error_map[VALIDATION_ERROR_00975]); 73195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 73205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7321b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7322946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (!skip) 73234a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdBindDescriptorSets(commandBuffer, pipelineBindPoint, layout, firstSet, setCount, 73244a0754042cf090e131e9e769d8a3633c228625beChris Forbes pDescriptorSets, dynamicOffsetCount, pDynamicOffsets); 73255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 73265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7327bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBindIndexBuffer(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, 7328bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkIndexType indexType) { 7329946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski bool skip = false; 733056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7331593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis // TODO : Somewhere need to verify that IBs have correct usage state flagged 7332b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7333b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski 73349a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto buffer_state = GetBufferState(dev_data, buffer); 73359a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, commandBuffer); 73365cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis if (cb_node && buffer_state) { 7337946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ValidateCmd(dev_data, cb_node, CMD_BINDINDEXBUFFER, "vkCmdBindIndexBuffer()"); 7338946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ValidateMemoryIsBoundToBuffer(dev_data, buffer_state, "vkCmdBindIndexBuffer()", VALIDATION_ERROR_02543); 7339ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski std::function<bool()> function = [=]() { 7340ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski return ValidateBufferMemoryIsValid(dev_data, buffer_state, "vkCmdBindIndexBuffer()"); 7341ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski }; 7342ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski cb_node->validate_functions.push_back(function); 7343ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski UpdateCmdBufferLastCmd(cb_node, CMD_BINDINDEXBUFFER); 7344ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski VkDeviceSize offset_align = 0; 7345ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski switch (indexType) { 7346ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski case VK_INDEX_TYPE_UINT16: 7347ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski offset_align = 2; 7348ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski break; 7349ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski case VK_INDEX_TYPE_UINT32: 7350ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski offset_align = 4; 7351ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski break; 7352ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski default: 7353ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski // ParamChecker should catch bad enum, we'll also throw alignment error below if offset_align stays 0 7354ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski break; 73555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7356ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski if (!offset_align || (offset % offset_align)) { 7357946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 7358946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski DRAWSTATE_VTX_INDEX_ALIGNMENT_ERROR, "DS", 7359946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "vkCmdBindIndexBuffer() offset (0x%" PRIxLEAST64 ") does not fall on alignment (%s) boundary.", offset, 7360946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski string_VkIndexType(indexType)); 7361ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } 7362ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski cb_node->status |= CBSTATUS_INDEX_BUFFER_BOUND; 7363ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } else { 7364ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis assert(0); 73655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7366b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7367946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdBindIndexBuffer(commandBuffer, buffer, offset, indexType); 73685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 73695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 73705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisvoid updateResourceTracking(GLOBAL_CB_NODE *pCB, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer *pBuffers) { 73715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t end = firstBinding + bindingCount; 73725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB->currentDrawData.buffers.size() < end) { 73735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->currentDrawData.buffers.resize(end); 73745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 73755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < bindingCount; ++i) { 73765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->currentDrawData.buffers[i + firstBinding] = pBuffers[i]; 73775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 73785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 73795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7380e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic inline void updateResourceTrackingOnDraw(GLOBAL_CB_NODE *pCB) { pCB->drawData.push_back(pCB->currentDrawData); } 73815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7382bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBindVertexBuffers(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, 7383bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkBuffer *pBuffers, const VkDeviceSize *pOffsets) { 7384946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski bool skip = false; 738556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7386593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis // TODO : Somewhere need to verify that VBs have correct usage state flagged 7387b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7388b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski 73899a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, commandBuffer); 73909f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis if (cb_node) { 7391946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ValidateCmd(dev_data, cb_node, CMD_BINDVERTEXBUFFER, "vkCmdBindVertexBuffer()"); 7392ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski for (uint32_t i = 0; i < bindingCount; ++i) { 7393ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski auto buffer_state = GetBufferState(dev_data, pBuffers[i]); 7394ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski assert(buffer_state); 7395946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ValidateMemoryIsBoundToBuffer(dev_data, buffer_state, "vkCmdBindVertexBuffers()", VALIDATION_ERROR_02546); 7396ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski std::function<bool()> function = [=]() { 7397ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski return ValidateBufferMemoryIsValid(dev_data, buffer_state, "vkCmdBindVertexBuffers()"); 7398ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski }; 7399ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski cb_node->validate_functions.push_back(function); 74005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7401ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski UpdateCmdBufferLastCmd(cb_node, CMD_BINDVERTEXBUFFER); 7402ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski updateResourceTracking(cb_node, firstBinding, bindingCount, pBuffers); 74035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 74047828015969ab31ee01d597f0288cbb124b637fcdMark Lobodzinski assert(0); 74055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7406b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7407946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdBindVertexBuffers(commandBuffer, firstBinding, bindingCount, pBuffers, pOffsets); 74085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 74095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 741025002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// Expects global_lock to be held by caller 74115569d6457ac22e7d245f3cdee045e71ffbc8b06eTobin Ehlisstatic void MarkStoreImagesAndBuffersAsWritten(layer_data *dev_data, GLOBAL_CB_NODE *pCB) { 74127a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis for (auto imageView : pCB->updateImages) { 74139a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto view_state = GetImageViewState(dev_data, imageView); 7414cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!view_state) continue; 7415249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis 74169a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_state = GetImageState(dev_data, view_state->create_info.image); 74171facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis assert(image_state); 7418e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves std::function<bool()> function = [=]() { 74191facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis SetImageMemoryValid(dev_data, image_state, true); 7420e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves return false; 74217a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis }; 74227a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis pCB->validate_functions.push_back(function); 74237a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis } 74247a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis for (auto buffer : pCB->updateBuffers) { 74259a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto buffer_state = GetBufferState(dev_data, buffer); 74265cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis assert(buffer_state); 7427e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves std::function<bool()> function = [=]() { 74285cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis SetBufferMemoryValid(dev_data, buffer_state, true); 7429e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves return false; 74307a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis }; 74317a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis pCB->validate_functions.push_back(function); 74325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 74335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 74345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7435ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis// Generic function to handle validation for all CmdDraw* type functions 7436ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool ValidateCmdDrawType(layer_data *dev_data, VkCommandBuffer cmd_buffer, bool indexed, VkPipelineBindPoint bind_point, 7437ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis CMD_TYPE cmd_type, GLOBAL_CB_NODE **cb_state, const char *caller, 74384f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes UNIQUE_VALIDATION_ERROR_CODE msg_code, UNIQUE_VALIDATION_ERROR_CODE const dynamic_state_msg_code) { 743958b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis bool skip = false; 74409a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *cb_state = GetCBNode(dev_data, cmd_buffer); 744158b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis if (*cb_state) { 7442ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis skip |= ValidateCmd(dev_data, *cb_state, cmd_type, caller); 74434f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes skip |= ValidateDrawState(dev_data, *cb_state, indexed, bind_point, caller, dynamic_state_msg_code); 744425d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis skip |= (VK_PIPELINE_BIND_POINT_GRAPHICS == bind_point) ? outsideRenderPass(dev_data, *cb_state, caller, msg_code) 744525d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis : insideRenderPass(dev_data, *cb_state, caller, msg_code); 744658b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis } 744758b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis return skip; 744858b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis} 744958b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis 745025d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis// Generic function to handle state update for all CmdDraw* and CmdDispatch* type functions 7451ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void UpdateStateCmdDrawDispatchType(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point, 7452ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis CMD_TYPE cmd_type) { 7453ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis UpdateDrawState(dev_data, cb_state, bind_point); 74542f921d33544c162dcb726fc3c7b915e89c02ff24Tobin Ehlis MarkStoreImagesAndBuffersAsWritten(dev_data, cb_state); 74551ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(cb_state, cmd_type); 745625d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis} 745725d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis 7458ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis// Generic function to handle state update for all CmdDraw* type functions 7459ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void UpdateStateCmdDrawType(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point, 7460ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis CMD_TYPE cmd_type, DRAW_TYPE draw_type) { 7461ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis UpdateStateCmdDrawDispatchType(dev_data, cb_state, bind_point, cmd_type); 7462c0b225e42808ba8fada7a2f67ecd662e376ccf15Tobin Ehlis updateResourceTrackingOnDraw(cb_state); 7463ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis cb_state->drawCount[draw_type]++; 7464ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis} 7465ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis 7466ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool PreCallValidateCmdDraw(layer_data *dev_data, VkCommandBuffer cmd_buffer, bool indexed, VkPipelineBindPoint bind_point, 7467ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis GLOBAL_CB_NODE **cb_state, const char *caller) { 74684f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes return ValidateCmdDrawType(dev_data, cmd_buffer, indexed, bind_point, CMD_DRAW, cb_state, caller, VALIDATION_ERROR_01365, 74694f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes VALIDATION_ERROR_02203); 7470ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis} 7471ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis 7472ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void PostCallRecordCmdDraw(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point) { 7473ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis UpdateStateCmdDrawType(dev_data, cb_state, bind_point, CMD_DRAW, DRAW); 7474c0b225e42808ba8fada7a2f67ecd662e376ccf15Tobin Ehlis} 7475c0b225e42808ba8fada7a2f67ecd662e376ccf15Tobin Ehlis 747689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount, 747789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu uint32_t firstVertex, uint32_t firstInstance) { 747856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 747958b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis GLOBAL_CB_NODE *cb_state = nullptr; 7480b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7481ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis bool skip = PreCallValidateCmdDraw(dev_data, commandBuffer, false, VK_PIPELINE_BIND_POINT_GRAPHICS, &cb_state, "vkCmdDraw()"); 7482b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 748358b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis if (!skip) { 74844a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdDraw(commandBuffer, vertexCount, instanceCount, firstVertex, firstInstance); 7485c0b225e42808ba8fada7a2f67ecd662e376ccf15Tobin Ehlis lock.lock(); 7486ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis PostCallRecordCmdDraw(dev_data, cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS); 7487c0b225e42808ba8fada7a2f67ecd662e376ccf15Tobin Ehlis lock.unlock(); 7488c0b225e42808ba8fada7a2f67ecd662e376ccf15Tobin Ehlis } 74895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 74905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7491ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool PreCallValidateCmdDrawIndexed(layer_data *dev_data, VkCommandBuffer cmd_buffer, bool indexed, 7492ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis VkPipelineBindPoint bind_point, GLOBAL_CB_NODE **cb_state, const char *caller) { 74934f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes return ValidateCmdDrawType(dev_data, cmd_buffer, indexed, bind_point, CMD_DRAWINDEXED, cb_state, caller, VALIDATION_ERROR_01372, 74944f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes VALIDATION_ERROR_02216); 7495ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis} 7496ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis 7497ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void PostCallRecordCmdDrawIndexed(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point) { 7498ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis UpdateStateCmdDrawType(dev_data, cb_state, bind_point, CMD_DRAWINDEXED, DRAW_INDEXED); 7499ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis} 7500ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis 7501bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount, 7502bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance) { 750356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7504ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis GLOBAL_CB_NODE *cb_state = nullptr; 7505b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7506ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis bool skip = PreCallValidateCmdDrawIndexed(dev_data, commandBuffer, true, VK_PIPELINE_BIND_POINT_GRAPHICS, &cb_state, 7507ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis "vkCmdDrawIndexed()"); 7508b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7509ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis if (!skip) { 75104a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdDrawIndexed(commandBuffer, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance); 7511ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis lock.lock(); 7512ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis PostCallRecordCmdDrawIndexed(dev_data, cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS); 7513ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis lock.unlock(); 7514ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis } 75155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 75165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7517ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool PreCallValidateCmdDrawIndirect(layer_data *dev_data, VkCommandBuffer cmd_buffer, VkBuffer buffer, bool indexed, 7518ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis VkPipelineBindPoint bind_point, GLOBAL_CB_NODE **cb_state, BUFFER_STATE **buffer_state, 7519ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis const char *caller) { 75204f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes bool skip = ValidateCmdDrawType(dev_data, cmd_buffer, indexed, bind_point, CMD_DRAWINDIRECT, cb_state, caller, 75214f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes VALIDATION_ERROR_01381, VALIDATION_ERROR_02234); 75229a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *buffer_state = GetBufferState(dev_data, buffer); 752335ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis skip |= ValidateMemoryIsBoundToBuffer(dev_data, *buffer_state, caller, VALIDATION_ERROR_02544); 7524d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis return skip; 7525d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis} 7526d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis 7527ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void PostCallRecordCmdDrawIndirect(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point, 7528ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis BUFFER_STATE *buffer_state) { 7529ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis UpdateStateCmdDrawType(dev_data, cb_state, bind_point, CMD_DRAWINDIRECT, DRAW_INDIRECT); 7530d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis AddCommandBufferBindingBuffer(dev_data, cb_state, buffer_state); 7531d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis} 7532d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis 7533bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count, 7534bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski uint32_t stride) { 753556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7536d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis GLOBAL_CB_NODE *cb_state = nullptr; 7537d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis BUFFER_STATE *buffer_state = nullptr; 7538b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7539872a2f0ca3ffdeddfa7483e777191fa64b853892Tony Barbour bool skip = PreCallValidateCmdDrawIndirect(dev_data, commandBuffer, buffer, false, VK_PIPELINE_BIND_POINT_GRAPHICS, &cb_state, 7540ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis &buffer_state, "vkCmdDrawIndirect()"); 7541b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7542d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis if (!skip) { 75434a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdDrawIndirect(commandBuffer, buffer, offset, count, stride); 7544d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis lock.lock(); 7545ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis PostCallRecordCmdDrawIndirect(dev_data, cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, buffer_state); 7546d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis lock.unlock(); 7547d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis } 75485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 75495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7550ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool PreCallValidateCmdDrawIndexedIndirect(layer_data *dev_data, VkCommandBuffer cmd_buffer, VkBuffer buffer, bool indexed, 7551ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis VkPipelineBindPoint bind_point, GLOBAL_CB_NODE **cb_state, 7552ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis BUFFER_STATE **buffer_state, const char *caller) { 7553ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis bool skip = ValidateCmdDrawType(dev_data, cmd_buffer, indexed, bind_point, CMD_DRAWINDEXEDINDIRECT, cb_state, caller, 75544f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes VALIDATION_ERROR_01393, VALIDATION_ERROR_02272); 75559a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *buffer_state = GetBufferState(dev_data, buffer); 755635ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis skip |= ValidateMemoryIsBoundToBuffer(dev_data, *buffer_state, caller, VALIDATION_ERROR_02545); 75570c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis return skip; 75580c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis} 75590c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis 7560ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void PostCallRecordCmdDrawIndexedIndirect(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point, 7561ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis BUFFER_STATE *buffer_state) { 7562ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis UpdateStateCmdDrawType(dev_data, cb_state, bind_point, CMD_DRAWINDEXEDINDIRECT, DRAW_INDEXED_INDIRECT); 75630c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis AddCommandBufferBindingBuffer(dev_data, cb_state, buffer_state); 75640c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis} 75650c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis 7566bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, 7567bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski uint32_t count, uint32_t stride) { 756856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 75690c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis GLOBAL_CB_NODE *cb_state = nullptr; 75700c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis BUFFER_STATE *buffer_state = nullptr; 7571b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 75720c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis bool skip = PreCallValidateCmdDrawIndexedIndirect(dev_data, commandBuffer, buffer, true, VK_PIPELINE_BIND_POINT_GRAPHICS, 7573ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis &cb_state, &buffer_state, "vkCmdDrawIndexedIndirect()"); 7574b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 75750c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis if (!skip) { 75764a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdDrawIndexedIndirect(commandBuffer, buffer, offset, count, stride); 75770c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis lock.lock(); 7578ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis PostCallRecordCmdDrawIndexedIndirect(dev_data, cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, buffer_state); 75790c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis lock.unlock(); 75800c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis } 75815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 75825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7583ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool PreCallValidateCmdDispatch(layer_data *dev_data, VkCommandBuffer cmd_buffer, bool indexed, 7584ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis VkPipelineBindPoint bind_point, GLOBAL_CB_NODE **cb_state, const char *caller) { 75854f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes return ValidateCmdDrawType(dev_data, cmd_buffer, indexed, bind_point, CMD_DISPATCH, cb_state, caller, VALIDATION_ERROR_01562, 75864f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes VALIDATION_ERROR_UNDEFINED); 758725d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis} 758825d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis 7589ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void PostCallRecordCmdDispatch(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point) { 7590ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis UpdateStateCmdDrawDispatchType(dev_data, cb_state, bind_point, CMD_DISPATCH); 759125d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis} 759225d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis 759389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z) { 759456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 759525d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis GLOBAL_CB_NODE *cb_state = nullptr; 7596b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7597ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis bool skip = 7598ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis PreCallValidateCmdDispatch(dev_data, commandBuffer, false, VK_PIPELINE_BIND_POINT_COMPUTE, &cb_state, "vkCmdDispatch()"); 7599b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 760025d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis if (!skip) { 76014a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdDispatch(commandBuffer, x, y, z); 760225d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis lock.lock(); 7603ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis PostCallRecordCmdDispatch(dev_data, cb_state, VK_PIPELINE_BIND_POINT_COMPUTE); 760425d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis lock.unlock(); 760525d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis } 76065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 76075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7608ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool PreCallValidateCmdDispatchIndirect(layer_data *dev_data, VkCommandBuffer cmd_buffer, VkBuffer buffer, bool indexed, 7609ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis VkPipelineBindPoint bind_point, GLOBAL_CB_NODE **cb_state, 7610ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis BUFFER_STATE **buffer_state, const char *caller) { 7611ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis bool skip = ValidateCmdDrawType(dev_data, cmd_buffer, indexed, bind_point, CMD_DISPATCHINDIRECT, cb_state, caller, 76124f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes VALIDATION_ERROR_01569, VALIDATION_ERROR_UNDEFINED); 76139a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *buffer_state = GetBufferState(dev_data, buffer); 761435ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis skip |= ValidateMemoryIsBoundToBuffer(dev_data, *buffer_state, caller, VALIDATION_ERROR_02547); 761579c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis return skip; 761679c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis} 761779c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis 7618ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void PostCallRecordCmdDispatchIndirect(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point, 7619ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis BUFFER_STATE *buffer_state) { 7620ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis UpdateStateCmdDrawDispatchType(dev_data, cb_state, bind_point, CMD_DISPATCHINDIRECT); 762179c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis AddCommandBufferBindingBuffer(dev_data, cb_state, buffer_state); 762279c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis} 762379c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis 7624bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset) { 762556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 762679c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis GLOBAL_CB_NODE *cb_state = nullptr; 762779c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis BUFFER_STATE *buffer_state = nullptr; 7628b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 76297433ab60c7ff16d37edb0f8b17b606ccd363e210Tobin Ehlis bool skip = PreCallValidateCmdDispatchIndirect(dev_data, commandBuffer, buffer, false, VK_PIPELINE_BIND_POINT_COMPUTE, 7630ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis &cb_state, &buffer_state, "vkCmdDispatchIndirect()"); 7631b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 763279c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis if (!skip) { 76334a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdDispatchIndirect(commandBuffer, buffer, offset); 763479c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis lock.lock(); 7635ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis PostCallRecordCmdDispatchIndirect(dev_data, cb_state, VK_PIPELINE_BIND_POINT_COMPUTE, buffer_state); 763679c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis lock.unlock(); 763779c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis } 76385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 76395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 764089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdCopyBuffer(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer, 764189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu uint32_t regionCount, const VkBufferCopy *pRegions) { 7642c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7643b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7644ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis 7645c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski auto cb_node = GetCBNode(device_data, commandBuffer); 7646c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski auto src_buffer_state = GetBufferState(device_data, srcBuffer); 7647c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski auto dst_buffer_state = GetBufferState(device_data, dstBuffer); 7648593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 7649c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski if (cb_node && src_buffer_state && dst_buffer_state) { 7650c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski bool skip = PreCallValidateCmdCopyBuffer(device_data, cb_node, src_buffer_state, dst_buffer_state); 7651c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski if (!skip) { 7652c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski PreCallRecordCmdCopyBuffer(device_data, cb_node, src_buffer_state, dst_buffer_state); 7653c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski lock.unlock(); 7654c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski device_data->dispatch_table.CmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, regionCount, pRegions); 7655c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski } 7656ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } else { 7657c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski lock.unlock(); 7658ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis assert(0); 76595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 76605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 76615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7662bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdCopyImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, 7663bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, 7664bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkImageCopy *pRegions) { 76656a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski bool skip = false; 76666a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7667b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7668249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis 76696a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski auto cb_node = GetCBNode(device_data, commandBuffer); 76706a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski auto src_image_state = GetImageState(device_data, srcImage); 76716a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski auto dst_image_state = GetImageState(device_data, dstImage); 76721facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis if (cb_node && src_image_state && dst_image_state) { 76736a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski skip = PreCallValidateCmdCopyImage(device_data, cb_node, src_image_state, dst_image_state, regionCount, pRegions, 76746a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski srcImageLayout, dstImageLayout); 76756a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski if (!skip) { 76766a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski PreCallRecordCmdCopyImage(device_data, cb_node, src_image_state, dst_image_state); 76776a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski lock.unlock(); 76786a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski device_data->dispatch_table.CmdCopyImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, 76796a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski pRegions); 76805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7681249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis } else { 76826a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski lock.unlock(); 7683249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis assert(0); 76845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 76855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 76865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7687eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski// Validate that an image's sampleCount matches the requirement for a specific API call 768860568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinskibool ValidateImageSampleCount(layer_data *dev_data, IMAGE_STATE *image_state, VkSampleCountFlagBits sample_count, 768960568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski const char *location, UNIQUE_VALIDATION_ERROR_CODE msgCode) { 7690eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski bool skip = false; 76911facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis if (image_state->createInfo.samples != sample_count) { 769255eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen skip = 769355eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 769455eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen reinterpret_cast<uint64_t &>(image_state->image), 0, msgCode, "DS", 769555eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen "%s for image 0x%" PRIxLEAST64 " was created with a sample count of %s but must be %s. %s", location, 769655eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen reinterpret_cast<uint64_t &>(image_state->image), string_VkSampleCountFlagBits(image_state->createInfo.samples), 769755eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen string_VkSampleCountFlagBits(sample_count), validation_error_map[msgCode]); 7698eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski } 7699eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski return skip; 7700eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski} 7701eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski 7702bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBlitImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, 7703bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, 7704bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkImageBlit *pRegions, VkFilter filter) { 770556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7706b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7707593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 77089a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, commandBuffer); 77099a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto src_image_state = GetImageState(dev_data, srcImage); 77109a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto dst_image_state = GetImageState(dev_data, dstImage); 77110dc51740dbd7b9f0ba7c071e0bf96f63d6d48c85Mark Lobodzinski 7712055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski bool skip = PreCallValidateCmdBlitImage(dev_data, cb_node, src_image_state, dst_image_state, regionCount, pRegions, filter); 77130dc51740dbd7b9f0ba7c071e0bf96f63d6d48c85Mark Lobodzinski 7714dca02371c9531e7a9a2a51decae1db4d297862c4Mark Lobodzinski if (!skip) { 7715eebd811afd800663f15fda8fc71bc203a03fe294Mark Lobodzinski PreCallRecordCmdBlitImage(dev_data, cb_node, src_image_state, dst_image_state); 7716eebd811afd800663f15fda8fc71bc203a03fe294Mark Lobodzinski lock.unlock(); 77174a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdBlitImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, 77184a0754042cf090e131e9e769d8a3633c228625beChris Forbes pRegions, filter); 77190dc51740dbd7b9f0ba7c071e0bf96f63d6d48c85Mark Lobodzinski } 77205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 77215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7722bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdCopyBufferToImage(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage, 7723bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkImageLayout dstImageLayout, uint32_t regionCount, 7724bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkBufferImageCopy *pRegions) { 7725940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7726b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7727940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski bool skip = false; 7728940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski auto cb_node = GetCBNode(device_data, commandBuffer); 7729940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski auto src_buffer_state = GetBufferState(device_data, srcBuffer); 7730940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski auto dst_image_state = GetImageState(device_data, dstImage); 7731940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski if (cb_node && src_buffer_state && dst_image_state) { 7732940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski skip = PreCallValidateCmdCopyBufferToImage(device_data, dstImageLayout, cb_node, src_buffer_state, dst_image_state, 773371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski regionCount, pRegions, "vkCmdCopyBufferToImage()"); 7734ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } else { 7735d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski lock.unlock(); 7736ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis assert(0); 7737e4d82c37d6c861b388dbc80297c18d6255858cb4Dave Houlton // TODO: report VU01244 here, or put in object tracker? 77385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7739940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski if (!skip) { 7740940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski PreCallRecordCmdCopyBufferToImage(device_data, cb_node, src_buffer_state, dst_image_state); 7741d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski lock.unlock(); 7742940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski device_data->dispatch_table.CmdCopyBufferToImage(commandBuffer, srcBuffer, dstImage, dstImageLayout, regionCount, pRegions); 7743d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski } 77445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 77455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7746bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdCopyImageToBuffer(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, 7747bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkBuffer dstBuffer, uint32_t regionCount, const VkBufferImageCopy *pRegions) { 7748940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski bool skip = false; 7749940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7750b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7751593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 7752940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski auto cb_node = GetCBNode(device_data, commandBuffer); 7753940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski auto src_image_state = GetImageState(device_data, srcImage); 7754940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski auto dst_buffer_state = GetBufferState(device_data, dstBuffer); 7755940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski if (cb_node && src_image_state && dst_buffer_state) { 7756940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski skip = PreCallValidateCmdCopyImageToBuffer(device_data, srcImageLayout, cb_node, src_image_state, dst_buffer_state, 775771c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski regionCount, pRegions, "vkCmdCopyImageToBuffer()"); 7758ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } else { 7759d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski lock.unlock(); 7760ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis assert(0); 7761e4d82c37d6c861b388dbc80297c18d6255858cb4Dave Houlton // TODO: report VU01262 here, or put in object tracker? 77625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7763940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski if (!skip) { 7764940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski PreCallRecordCmdCopyImageToBuffer(device_data, cb_node, src_image_state, dst_buffer_state); 7765d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski lock.unlock(); 7766940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski device_data->dispatch_table.CmdCopyImageToBuffer(commandBuffer, srcImage, srcImageLayout, dstBuffer, regionCount, pRegions); 7767d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski } 77685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 77695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7770bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdUpdateBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, 7771bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDeviceSize dataSize, const uint32_t *pData) { 777283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 777356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7774b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7775593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 77769a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, commandBuffer); 77779a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto dst_buff_state = GetBufferState(dev_data, dstBuffer); 77785cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis if (cb_node && dst_buff_state) { 777935ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, dst_buff_state, "vkCmdUpdateBuffer()", VALIDATION_ERROR_02530); 7780ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis // Update bindings between buffer and cmd buffer 77815cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis AddCommandBufferBindingBuffer(dev_data, cb_node, dst_buff_state); 7782ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis // Validate that DST buffer has correct usage flags set 77835cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis skip_call |= ValidateBufferUsageFlags(dev_data, dst_buff_state, VK_BUFFER_USAGE_TRANSFER_DST_BIT, true, 77841b8a6bd9260c52ca6c6cfe1e34f142f93e1e2cc6Jeremy Hayes VALIDATION_ERROR_01146, "vkCmdUpdateBuffer()", "VK_BUFFER_USAGE_TRANSFER_DST_BIT"); 7785e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves std::function<bool()> function = [=]() { 77865cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis SetBufferMemoryValid(dev_data, dst_buff_state, true); 7787e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves return false; 77885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis }; 77899f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis cb_node->validate_functions.push_back(function); 7790593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 779129f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, cb_node, CMD_UPDATEBUFFER, "vkCmdUpdateBuffer()"); 77921ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(cb_node, CMD_UPDATEBUFFER); 7793ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen skip_call |= insideRenderPass(dev_data, cb_node, "vkCmdUpdateBuffer()", VALIDATION_ERROR_01155); 7794ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } else { 7795ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis assert(0); 77965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7797b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7798cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.CmdUpdateBuffer(commandBuffer, dstBuffer, dstOffset, dataSize, pData); 77995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 78005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7801bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdFillBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, 7802bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDeviceSize size, uint32_t data) { 780323bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7804b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 780523bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski auto cb_node = GetCBNode(device_data, commandBuffer); 780623bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski auto buffer_state = GetBufferState(device_data, dstBuffer); 7807593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 780823bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski if (cb_node && buffer_state) { 780923bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski bool skip = PreCallValidateCmdFillBuffer(device_data, cb_node, buffer_state); 781023bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski if (!skip) { 781123bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski PreCallRecordCmdFillBuffer(device_data, cb_node, buffer_state); 781223bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski lock.unlock(); 781323bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski device_data->dispatch_table.CmdFillBuffer(commandBuffer, dstBuffer, dstOffset, size, data); 781423bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski } 7815ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } else { 781623bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski lock.unlock(); 7817ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis assert(0); 78185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 78195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 78205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 78214028af23e688ab5730f48ab2244dd042e2eefaedMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdClearAttachments(VkCommandBuffer commandBuffer, uint32_t attachmentCount, 78224028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski const VkClearAttachment *pAttachments, uint32_t rectCount, 78234028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski const VkClearRect *pRects) { 78244028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski bool skip = false; 782556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 78264028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski { 78274028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski std::lock_guard<std::mutex> lock(global_lock); 78284028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski skip = PreCallValidateCmdClearAttachments(dev_data, commandBuffer, attachmentCount, pAttachments, rectCount, pRects); 78294028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski } 7830cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdClearAttachments(commandBuffer, attachmentCount, pAttachments, rectCount, pRects); 78315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 78325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 78330482c55760707900fcd072f6895c121bcf055f6eMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdClearColorImage(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, 78340482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski const VkClearColorValue *pColor, uint32_t rangeCount, 78350482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski const VkImageSubresourceRange *pRanges) { 783656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7837b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 78380482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski 78390482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski bool skip = PreCallValidateCmdClearColorImage(dev_data, commandBuffer, image, imageLayout, rangeCount, pRanges); 78400482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski if (!skip) { 78410482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski PreCallRecordCmdClearImage(dev_data, commandBuffer, image, imageLayout, rangeCount, pRanges, CMD_CLEARCOLORIMAGE); 78420482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski lock.unlock(); 78430482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski dev_data->dispatch_table.CmdClearColorImage(commandBuffer, image, imageLayout, pColor, rangeCount, pRanges); 78440482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski } 78450482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski} 78460482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski 78470482c55760707900fcd072f6895c121bcf055f6eMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdClearDepthStencilImage(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, 78480482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski const VkClearDepthStencilValue *pDepthStencil, uint32_t rangeCount, 78490482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski const VkImageSubresourceRange *pRanges) { 785056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 78510482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski std::unique_lock<std::mutex> lock(global_lock); 78520482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski 78530482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski bool skip = PreCallValidateCmdClearDepthStencilImage(dev_data, commandBuffer, image, imageLayout, rangeCount, pRanges); 78540482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski if (!skip) { 78550482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski PreCallRecordCmdClearImage(dev_data, commandBuffer, image, imageLayout, rangeCount, pRanges, CMD_CLEARDEPTHSTENCILIMAGE); 78560482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski lock.unlock(); 78570482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski dev_data->dispatch_table.CmdClearDepthStencilImage(commandBuffer, image, imageLayout, pDepthStencil, rangeCount, pRanges); 78587f8aa8f5abceedbb599ef69af1dfbb38c0df2660Slawomir Cygan } 78595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 78605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7861bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdResolveImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, 7862bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, 7863bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkImageResolve *pRegions) { 786456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7865b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7866593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 78679a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, commandBuffer); 78689a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto src_image_state = GetImageState(dev_data, srcImage); 78699a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto dst_image_state = GetImageState(dev_data, dstImage); 787009fe5ac5edaec7f0dbcc9fd696e68194569aea89Mark Lobodzinski 787125f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski bool skip = PreCallValidateCmdResolveImage(dev_data, cb_node, src_image_state, dst_image_state, regionCount, pRegions); 787209fe5ac5edaec7f0dbcc9fd696e68194569aea89Mark Lobodzinski 787309fe5ac5edaec7f0dbcc9fd696e68194569aea89Mark Lobodzinski if (!skip) { 78746c0400e625554ce7fddb833eeace0de19cfcc965Mark Lobodzinski PreCallRecordCmdResolveImage(dev_data, cb_node, src_image_state, dst_image_state); 78756c0400e625554ce7fddb833eeace0de19cfcc965Mark Lobodzinski lock.unlock(); 78764a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdResolveImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, 78774a0754042cf090e131e9e769d8a3633c228625beChris Forbes pRegions); 787809fe5ac5edaec7f0dbcc9fd696e68194569aea89Mark Lobodzinski } 78795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 78805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7881a8d1e377bdeaf61a3209cb997502da4356a185bbMike WeiblenVKAPI_ATTR void VKAPI_CALL GetImageSubresourceLayout(VkDevice device, VkImage image, const VkImageSubresource *pSubresource, 7882a8d1e377bdeaf61a3209cb997502da4356a185bbMike Weiblen VkSubresourceLayout *pLayout) { 7883a8d1e377bdeaf61a3209cb997502da4356a185bbMike Weiblen layer_data *device_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 7884a8d1e377bdeaf61a3209cb997502da4356a185bbMike Weiblen 7885a8d1e377bdeaf61a3209cb997502da4356a185bbMike Weiblen bool skip = PreCallValidateGetImageSubresourceLayout(device_data, image, pSubresource); 7886a8d1e377bdeaf61a3209cb997502da4356a185bbMike Weiblen if (!skip) { 7887b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski device_data->dispatch_table.GetImageSubresourceLayout(device, image, pSubresource, pLayout); 7888b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski } 7889b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski} 7890b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski 7891b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentinebool setEventStageMask(VkQueue queue, VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) { 789256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 78939a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 7894b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine if (pCB) { 7895b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine pCB->eventToStageMap[event] = stageMask; 7896b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine } 7897b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine auto queue_data = dev_data->queueMap.find(queue); 7898b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine if (queue_data != dev_data->queueMap.end()) { 7899b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine queue_data->second.eventToStageMap[event] = stageMask; 7900b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine } 7901b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine return false; 7902b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine} 7903b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine 7904bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) { 790583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 790656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7907b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 79089a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 79095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 791029f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_SETEVENT, "vkCmdSetEvent()"); 79111ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETEVENT); 7912ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen skip_call |= insideRenderPass(dev_data, pCB, "vkCmdSetEvent()", VALIDATION_ERROR_00238); 7913208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis skip_call |= 7914208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis ValidateStageMaskGsTsEnables(dev_data, stageMask, "vkCmdSetEvent()", VALIDATION_ERROR_00230, VALIDATION_ERROR_00231); 79159a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto event_state = GetEventNode(dev_data, event); 79164710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis if (event_state) { 79174710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis addCommandBufferBinding(&event_state->cb_bindings, 7918ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis {reinterpret_cast<uint64_t &>(event), VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT}, pCB); 79194710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis event_state->cb_bindings.insert(pCB); 7920ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis } 79215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->events.push_back(event); 7922c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine if (!pCB->waitedEvents.count(event)) { 7923c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine pCB->writeEventsBeforeWait.push_back(event); 7924c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine } 7925b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine std::function<bool(VkQueue)> eventUpdate = 7926b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine std::bind(setEventStageMask, std::placeholders::_1, commandBuffer, event, stageMask); 7927b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine pCB->eventUpdates.push_back(eventUpdate); 79285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7929b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7930cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.CmdSetEvent(commandBuffer, event, stageMask); 79315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 79325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7933bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdResetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) { 793483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 793556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7936b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 79379a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 79385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 793929f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_RESETEVENT, "vkCmdResetEvent()"); 79401ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_RESETEVENT); 7941ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen skip_call |= insideRenderPass(dev_data, pCB, "vkCmdResetEvent()", VALIDATION_ERROR_00249); 7942208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis skip_call |= 7943208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis ValidateStageMaskGsTsEnables(dev_data, stageMask, "vkCmdResetEvent()", VALIDATION_ERROR_00240, VALIDATION_ERROR_00241); 79449a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto event_state = GetEventNode(dev_data, event); 79454710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis if (event_state) { 79464710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis addCommandBufferBinding(&event_state->cb_bindings, 7947ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis {reinterpret_cast<uint64_t &>(event), VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT}, pCB); 79484710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis event_state->cb_bindings.insert(pCB); 7949ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis } 79505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->events.push_back(event); 7951c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine if (!pCB->waitedEvents.count(event)) { 7952c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine pCB->writeEventsBeforeWait.push_back(event); 7953c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine } 7954208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis // TODO : Add check for VALIDATION_ERROR_00226 7955b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine std::function<bool(VkQueue)> eventUpdate = 7956b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine std::bind(setEventStageMask, std::placeholders::_1, commandBuffer, event, VkPipelineStageFlags(0)); 7957b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine pCB->eventUpdates.push_back(eventUpdate); 79585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7959b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7960cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.CmdResetEvent(commandBuffer, event, stageMask); 79615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 79625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7963e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool ValidateBarriers(const char *funcName, VkCommandBuffer cmdBuffer, uint32_t memBarrierCount, 7964e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves const VkMemoryBarrier *pMemBarriers, uint32_t bufferBarrierCount, 7965e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves const VkBufferMemoryBarrier *pBufferMemBarriers, uint32_t imageMemBarrierCount, 7966e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves const VkImageMemoryBarrier *pImageMemBarriers) { 7967a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis bool skip = false; 796856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(cmdBuffer), layer_data_map); 79699a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, cmdBuffer); 79705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB->activeRenderPass && memBarrierCount) { 7971ee691f5c5fa87aac3750454d2bca2cb582e4e817Chris Forbes if (!pCB->activeRenderPass->hasSelfDependency[pCB->activeSubpass]) { 7972a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 7973cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski DRAWSTATE_INVALID_BARRIER, "DS", 7974cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s: Barriers cannot be set during subpass %d " 7975cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "with no self dependency specified.", 7976a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis funcName, pCB->activeSubpass); 79775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 79785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 79795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < imageMemBarrierCount; ++i) { 79805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto mem_barrier = &pImageMemBarriers[i]; 79819a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_data = GetImageState(dev_data, mem_barrier->image); 79826d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis if (image_data) { 79835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t src_q_f_index = mem_barrier->srcQueueFamilyIndex; 79845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t dst_q_f_index = mem_barrier->dstQueueFamilyIndex; 79856d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis if (image_data->createInfo.sharingMode == VK_SHARING_MODE_CONCURRENT) { 79865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // srcQueueFamilyIndex and dstQueueFamilyIndex must both 79875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // be VK_QUEUE_FAMILY_IGNORED 79885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if ((src_q_f_index != VK_QUEUE_FAMILY_IGNORED) || (dst_q_f_index != VK_QUEUE_FAMILY_IGNORED)) { 7989cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski skip |= 7990cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 7991cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski DRAWSTATE_INVALID_QUEUE_INDEX, "DS", "%s: Image Barrier for image 0x%" PRIx64 7992cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " was created with sharingMode of " 7993cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "VK_SHARING_MODE_CONCURRENT. Src and dst " 7994cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "queueFamilyIndices must be VK_QUEUE_FAMILY_IGNORED.", 7995cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski funcName, reinterpret_cast<const uint64_t &>(mem_barrier->image)); 79965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 79975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 79985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Sharing mode is VK_SHARING_MODE_EXCLUSIVE. srcQueueFamilyIndex and 79995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // dstQueueFamilyIndex must either both be VK_QUEUE_FAMILY_IGNORED, 80005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // or both be a valid queue family 80015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (((src_q_f_index == VK_QUEUE_FAMILY_IGNORED) || (dst_q_f_index == VK_QUEUE_FAMILY_IGNORED)) && 80025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (src_q_f_index != dst_q_f_index)) { 8003a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis skip |= 80045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 8005cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski DRAWSTATE_INVALID_QUEUE_INDEX, "DS", "%s: Image 0x%" PRIx64 8006cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " was created with sharingMode " 80075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis "of VK_SHARING_MODE_EXCLUSIVE. If one of src- or " 80085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis "dstQueueFamilyIndex is VK_QUEUE_FAMILY_IGNORED, both " 80095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis "must be.", 80105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis funcName, reinterpret_cast<const uint64_t &>(mem_barrier->image)); 80115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (((src_q_f_index != VK_QUEUE_FAMILY_IGNORED) && (dst_q_f_index != VK_QUEUE_FAMILY_IGNORED)) && 8012b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis ((src_q_f_index >= dev_data->phys_dev_properties.queue_family_properties.size()) || 8013b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis (dst_q_f_index >= dev_data->phys_dev_properties.queue_family_properties.size()))) { 8014a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 8015a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis __LINE__, DRAWSTATE_INVALID_QUEUE_INDEX, "DS", 8016cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s: Image 0x%" PRIx64 8017cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " was created with sharingMode " 8018a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis "of VK_SHARING_MODE_EXCLUSIVE, but srcQueueFamilyIndex %d" 8019a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis " or dstQueueFamilyIndex %d is greater than " PRINTF_SIZE_T_SPECIFIER 8020a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis "queueFamilies crated for this device.", 8021a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis funcName, reinterpret_cast<const uint64_t &>(mem_barrier->image), src_q_f_index, dst_q_f_index, 8022a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis dev_data->phys_dev_properties.queue_family_properties.size()); 80235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 80245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 80255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 80265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 80275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (mem_barrier) { 8028d678ec4f57d80aa89c24562e9ffe941d8d69e455Tony Barbour if (mem_barrier->oldLayout != mem_barrier->newLayout) { 8029a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis skip |= 8030d678ec4f57d80aa89c24562e9ffe941d8d69e455Tony Barbour ValidateMaskBitsFromLayouts(dev_data, cmdBuffer, mem_barrier->srcAccessMask, mem_barrier->oldLayout, "Source"); 8031a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis skip |= 8032d678ec4f57d80aa89c24562e9ffe941d8d69e455Tony Barbour ValidateMaskBitsFromLayouts(dev_data, cmdBuffer, mem_barrier->dstAccessMask, mem_barrier->newLayout, "Dest"); 8033d678ec4f57d80aa89c24562e9ffe941d8d69e455Tony Barbour } 80345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (mem_barrier->newLayout == VK_IMAGE_LAYOUT_UNDEFINED || mem_barrier->newLayout == VK_IMAGE_LAYOUT_PREINITIALIZED) { 8035a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 8036cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski DRAWSTATE_INVALID_BARRIER, "DS", 8037cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s: Image Layout cannot be transitioned to UNDEFINED or " 8038cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "PREINITIALIZED.", 8039a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis funcName); 80405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 80411d5109d5e0dcc530b27e632e73e1be5e12a28dcdJamie Madill VkFormat format = VK_FORMAT_UNDEFINED; 80421d5109d5e0dcc530b27e632e73e1be5e12a28dcdJamie Madill uint32_t arrayLayers = 0, mipLevels = 0; 80435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool imageFound = false; 80446d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis if (image_data) { 80456d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis format = image_data->createInfo.format; 80466d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis arrayLayers = image_data->createInfo.arrayLayers; 80476d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis mipLevels = image_data->createInfo.mipLevels; 80485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis imageFound = true; 80495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (dev_data->device_extensions.wsi_enabled) { 80509a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto imageswap_data = GetSwapchainFromImage(dev_data, mem_barrier->image); 8051170dc65b45f6bcdec47e02b3aa19435e55b32804Tobin Ehlis if (imageswap_data) { 80529a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto swapchain_data = GetSwapchainNode(dev_data, imageswap_data); 8053b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis if (swapchain_data) { 8054b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis format = swapchain_data->createInfo.imageFormat; 8055b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis arrayLayers = swapchain_data->createInfo.imageArrayLayers; 80565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis mipLevels = 1; 80575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis imageFound = true; 80585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 80595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 80605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 80615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (imageFound) { 8062e08b485346524a30ddfe6526f7dcbbf78c776d10Mark Lobodzinski skip |= ValidateImageSubrangeLevelLayerCounts(dev_data, mem_barrier->subresourceRange, funcName); 8063c37c65e9ff3a0abc86e706ee61d21e1dec882731Tobin Ehlis auto aspect_mask = mem_barrier->subresourceRange.aspectMask; 8064a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis skip |= ValidateImageAspectMask(dev_data, image_data->image, format, aspect_mask, funcName); 8065f0d091deca3d4b90e1f31d75e062684dca160ad1Michael Lentine int layerCount = (mem_barrier->subresourceRange.layerCount == VK_REMAINING_ARRAY_LAYERS) 8066f0d091deca3d4b90e1f31d75e062684dca160ad1Michael Lentine ? 1 8067f0d091deca3d4b90e1f31d75e062684dca160ad1Michael Lentine : mem_barrier->subresourceRange.layerCount; 8068f0d091deca3d4b90e1f31d75e062684dca160ad1Michael Lentine if ((mem_barrier->subresourceRange.baseArrayLayer + layerCount) > arrayLayers) { 8069a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 8070cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, DRAWSTATE_INVALID_BARRIER, "DS", 8071cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s: Subresource must have the sum of the " 8072cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "baseArrayLayer (%d) and layerCount (%d) be less " 8073cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "than or equal to the total number of layers (%d).", 8074a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis funcName, mem_barrier->subresourceRange.baseArrayLayer, 8075a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis mem_barrier->subresourceRange.layerCount, arrayLayers); 80765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8077f0d091deca3d4b90e1f31d75e062684dca160ad1Michael Lentine int levelCount = (mem_barrier->subresourceRange.levelCount == VK_REMAINING_MIP_LEVELS) 8078f0d091deca3d4b90e1f31d75e062684dca160ad1Michael Lentine ? 1 8079f0d091deca3d4b90e1f31d75e062684dca160ad1Michael Lentine : mem_barrier->subresourceRange.levelCount; 8080f0d091deca3d4b90e1f31d75e062684dca160ad1Michael Lentine if ((mem_barrier->subresourceRange.baseMipLevel + levelCount) > mipLevels) { 8081cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 8082cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, DRAWSTATE_INVALID_BARRIER, "DS", 8083cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s: Subresource must have the sum of the baseMipLevel " 8084cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "(%d) and levelCount (%d) be less than or equal to " 8085cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "the total number of levels (%d).", 8086cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski funcName, mem_barrier->subresourceRange.baseMipLevel, mem_barrier->subresourceRange.levelCount, 8087cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski mipLevels); 80885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 80895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 80905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 80915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 80925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < bufferBarrierCount; ++i) { 80935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto mem_barrier = &pBufferMemBarriers[i]; 80945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB->activeRenderPass) { 8095a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 8096a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis DRAWSTATE_INVALID_BARRIER, "DS", "%s: Buffer Barriers cannot be used during a render pass.", funcName); 80975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8098cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!mem_barrier) continue; 80995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 81005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Validate buffer barrier queue family indices 81015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if ((mem_barrier->srcQueueFamilyIndex != VK_QUEUE_FAMILY_IGNORED && 8102b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis mem_barrier->srcQueueFamilyIndex >= dev_data->phys_dev_properties.queue_family_properties.size()) || 81035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (mem_barrier->dstQueueFamilyIndex != VK_QUEUE_FAMILY_IGNORED && 8104b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis mem_barrier->dstQueueFamilyIndex >= dev_data->phys_dev_properties.queue_family_properties.size())) { 8105a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 8106a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis DRAWSTATE_INVALID_QUEUE_INDEX, "DS", 8107cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s: Buffer Barrier 0x%" PRIx64 8108cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " has QueueFamilyIndex greater " 8109a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis "than the number of QueueFamilies (" PRINTF_SIZE_T_SPECIFIER ") for this device.", 8110a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis funcName, reinterpret_cast<const uint64_t &>(mem_barrier->buffer), 8111a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis dev_data->phys_dev_properties.queue_family_properties.size()); 81125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 81135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 81149a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto buffer_state = GetBufferState(dev_data, mem_barrier->buffer); 81155cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis if (buffer_state) { 81165cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis auto buffer_size = buffer_state->requirements.size; 81175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (mem_barrier->offset >= buffer_size) { 8118a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 8119a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis DRAWSTATE_INVALID_BARRIER, "DS", "%s: Buffer Barrier 0x%" PRIx64 " has offset 0x%" PRIx64 8120a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis " which is not less than total size 0x%" PRIx64 ".", 8121a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis funcName, reinterpret_cast<const uint64_t &>(mem_barrier->buffer), 8122a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis reinterpret_cast<const uint64_t &>(mem_barrier->offset), 8123a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis reinterpret_cast<const uint64_t &>(buffer_size)); 81245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (mem_barrier->size != VK_WHOLE_SIZE && (mem_barrier->offset + mem_barrier->size > buffer_size)) { 8125a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis skip |= log_msg( 812694c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 8127414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller DRAWSTATE_INVALID_BARRIER, "DS", "%s: Buffer Barrier 0x%" PRIx64 " has offset 0x%" PRIx64 " and size 0x%" PRIx64 8128414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller " whose sum is greater than total size 0x%" PRIx64 ".", 812994c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis funcName, reinterpret_cast<const uint64_t &>(mem_barrier->buffer), 813094c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis reinterpret_cast<const uint64_t &>(mem_barrier->offset), reinterpret_cast<const uint64_t &>(mem_barrier->size), 813194c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis reinterpret_cast<const uint64_t &>(buffer_size)); 81325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 81335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 81345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8135a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis return skip; 81365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 81375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8138bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskibool validateEventStageMask(VkQueue queue, GLOBAL_CB_NODE *pCB, uint32_t eventCount, size_t firstEventIndex, 8139bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkPipelineStageFlags sourceStageMask) { 8140b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine bool skip_call = false; 8141b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine VkPipelineStageFlags stageMask = 0; 814256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map); 8143b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine for (uint32_t i = 0; i < eventCount; ++i) { 81442ab14387df9b890fe4b13494ea249dd03cf898d2Chris Forbes auto event = pCB->events[firstEventIndex + i]; 8145b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine auto queue_data = dev_data->queueMap.find(queue); 8146cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (queue_data == dev_data->queueMap.end()) return false; 81472ab14387df9b890fe4b13494ea249dd03cf898d2Chris Forbes auto event_data = queue_data->second.eventToStageMap.find(event); 8148b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine if (event_data != queue_data->second.eventToStageMap.end()) { 8149b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine stageMask |= event_data->second; 8150b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine } else { 81519a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto global_event_data = GetEventNode(dev_data, event); 81529556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis if (!global_event_data) { 8153b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT, 815427c3e0dda9e30d1d334728bbd373e8d7011257d4Chris Forbes reinterpret_cast<const uint64_t &>(event), __LINE__, DRAWSTATE_INVALID_EVENT, "DS", 815527c3e0dda9e30d1d334728bbd373e8d7011257d4Chris Forbes "Event 0x%" PRIx64 " cannot be waited on if it has never been set.", 81562ab14387df9b890fe4b13494ea249dd03cf898d2Chris Forbes reinterpret_cast<const uint64_t &>(event)); 8157b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine } else { 81589556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis stageMask |= global_event_data->stageMask; 8159b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine } 8160b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine } 8161b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine } 8162c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine // TODO: Need to validate that host_bit is only set if set event is called 8163c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine // but set event can be called at any time. 8164c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine if (sourceStageMask != stageMask && sourceStageMask != (stageMask | VK_PIPELINE_STAGE_HOST_BIT)) { 8165c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 8166cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VALIDATION_ERROR_00254, "DS", 8167cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Submitting cmdbuffer with call to VkCmdWaitEvents " 8168cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "using srcStageMask 0x%X which must be the bitwise " 8169cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "OR of the stageMask parameters used in calls to " 8170cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkCmdSetEvent and VK_PIPELINE_STAGE_HOST_BIT if " 8171cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "used with vkSetEvent but instead is 0x%X. %s", 81729bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt sourceStageMask, stageMask, validation_error_map[VALIDATION_ERROR_00254]); 8173b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine } 8174b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine return skip_call; 8175b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine} 8176b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine 817707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski// Note that we only check bits that HAVE required queueflags -- don't care entries are skipped 817807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinskistatic std::unordered_map<VkPipelineStageFlags, VkQueueFlags> supported_pipeline_stages_table = { 817907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX, VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT}, 818007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT}, 818107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_QUEUE_GRAPHICS_BIT}, 818207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, VK_QUEUE_GRAPHICS_BIT}, 818307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT, VK_QUEUE_GRAPHICS_BIT}, 818407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT, VK_QUEUE_GRAPHICS_BIT}, 818507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT, VK_QUEUE_GRAPHICS_BIT}, 818607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_QUEUE_GRAPHICS_BIT}, 818707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, VK_QUEUE_GRAPHICS_BIT}, 818807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_QUEUE_GRAPHICS_BIT}, 818907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_QUEUE_GRAPHICS_BIT}, 819007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_QUEUE_COMPUTE_BIT}, 819107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_TRANSFER_BIT, VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT}, 819207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_QUEUE_GRAPHICS_BIT}}; 819307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski 819407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinskistatic const VkPipelineStageFlags stage_flag_bit_array[] = {VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX, 819507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, 819607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 819707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, 819807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT, 819907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT, 820007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT, 820107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 820207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, 820307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, 820407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 820507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 820607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_TRANSFER_BIT, 820707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT}; 820807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski 820907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinskibool CheckStageMaskQueueCompatibility(layer_data *dev_data, VkCommandBuffer command_buffer, VkPipelineStageFlags stage_mask, 821007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VkQueueFlags queue_flags, const char *function, const char *src_or_dest, 821107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski UNIQUE_VALIDATION_ERROR_CODE error_code) { 821207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski bool skip = false; 821307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski // Lookup each bit in the stagemask and check for overlap between its table bits and queue_flags 821407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski for (const auto &item : stage_flag_bit_array) { 821507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski if (stage_mask & item) { 821607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski if ((supported_pipeline_stages_table[item] & queue_flags) == 0) { 821707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski skip |= 821807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 821907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski reinterpret_cast<uint64_t &>(command_buffer), __LINE__, error_code, "DL", 822007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski "%s(): %s flag %s is not compatible with the queue family properties of this " 822107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski "command buffer. %s", 822207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski function, src_or_dest, string_VkPipelineStageFlagBits(static_cast<VkPipelineStageFlagBits>(item)), 822307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski validation_error_map[error_code]); 822407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski } 822507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski } 822607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski } 822707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski return skip; 822807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski} 822907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski 823007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinskibool ValidateStageMasksAgainstQueueCapabilities(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, 823107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VkPipelineStageFlags source_stage_mask, VkPipelineStageFlags dest_stage_mask, 823207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski const char *function, UNIQUE_VALIDATION_ERROR_CODE error_code) { 823307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski bool skip = false; 823407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski uint32_t queue_family_index = dev_data->commandPoolMap[cb_state->createInfo.commandPool].queueFamilyIndex; 823556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(dev_data->physical_device), instance_layer_data_map); 82369a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto physical_device_state = GetPhysicalDeviceState(instance_data, dev_data->physical_device); 823707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski 823807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski // Any pipeline stage included in srcStageMask or dstStageMask must be supported by the capabilities of the queue family 823907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski // specified by the queueFamilyIndex member of the VkCommandPoolCreateInfo structure that was used to create the VkCommandPool 824007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski // that commandBuffer was allocated from, as specified in the table of supported pipeline stages. 824107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski 824207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski if (queue_family_index < physical_device_state->queue_family_properties.size()) { 824307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VkQueueFlags specified_queue_flags = physical_device_state->queue_family_properties[queue_family_index].queueFlags; 824407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski 824507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski if ((source_stage_mask & VK_PIPELINE_STAGE_ALL_COMMANDS_BIT) == 0) { 824607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski skip |= CheckStageMaskQueueCompatibility(dev_data, cb_state->commandBuffer, source_stage_mask, specified_queue_flags, 824707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski function, "srcStageMask", error_code); 824807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski } 824907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski if ((dest_stage_mask & VK_PIPELINE_STAGE_ALL_COMMANDS_BIT) == 0) { 825007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski skip |= CheckStageMaskQueueCompatibility(dev_data, cb_state->commandBuffer, dest_stage_mask, specified_queue_flags, 825107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski function, "dstStageMask", error_code); 825207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski } 825307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski } 825407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski return skip; 825507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski} 825607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski 8257d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent *pEvents, 8258d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski VkPipelineStageFlags sourceStageMask, VkPipelineStageFlags dstStageMask, 8259d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers, 8260d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers, 8261d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers) { 8262d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski bool skip = false; 826356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 8264b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 82659a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer); 8266d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski if (cb_state) { 8267d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski skip |= ValidateStageMasksAgainstQueueCapabilities(dev_data, cb_state, sourceStageMask, dstStageMask, "vkCmdWaitEvents", 8268d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski VALIDATION_ERROR_02510); 8269208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis skip |= ValidateStageMaskGsTsEnables(dev_data, sourceStageMask, "vkCmdWaitEvents()", VALIDATION_ERROR_02067, 8270208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis VALIDATION_ERROR_02069); 8271208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis skip |= ValidateStageMaskGsTsEnables(dev_data, dstStageMask, "vkCmdWaitEvents()", VALIDATION_ERROR_02068, 8272208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis VALIDATION_ERROR_02070); 8273d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski auto first_event_index = cb_state->events.size(); 82745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < eventCount; ++i) { 82759a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto event_state = GetEventNode(dev_data, pEvents[i]); 82764710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis if (event_state) { 82774710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis addCommandBufferBinding(&event_state->cb_bindings, 8278ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis {reinterpret_cast<const uint64_t &>(pEvents[i]), VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT}, 8279d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski cb_state); 8280d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski event_state->cb_bindings.insert(cb_state); 8281ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis } 8282d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski cb_state->waitedEvents.insert(pEvents[i]); 8283d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski cb_state->events.push_back(pEvents[i]); 82845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8285d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski std::function<bool(VkQueue)> event_update = 8286d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski std::bind(validateEventStageMask, std::placeholders::_1, cb_state, eventCount, first_event_index, sourceStageMask); 8287d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski cb_state->eventUpdates.push_back(event_update); 8288ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski skip |= ValidateCmd(dev_data, cb_state, CMD_WAITEVENTS, "vkCmdWaitEvents()"); 8289ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski UpdateCmdBufferLastCmd(cb_state, CMD_WAITEVENTS); 8290e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski skip |= ValidateImageLayouts(dev_data, commandBuffer, imageMemoryBarrierCount, pImageMemoryBarriers); 8291e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski if (!skip) { 8292e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski TransitionImageLayouts(dev_data, commandBuffer, imageMemoryBarrierCount, pImageMemoryBarriers); 8293e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski } 8294e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski 8295364a03b109f0b2b37be2e13d293fa93b8af5203aMike Weiblen skip |= ValidateBarriers("vkCmdWaitEvents()", commandBuffer, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, 8296d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers); 82975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8298b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 8299d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski if (!skip) 83004a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdWaitEvents(commandBuffer, eventCount, pEvents, sourceStageMask, dstStageMask, 83014a0754042cf090e131e9e769d8a3633c228625beChris Forbes memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, 83024a0754042cf090e131e9e769d8a3633c228625beChris Forbes imageMemoryBarrierCount, pImageMemoryBarriers); 83035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 83045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 830503122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinskistatic bool PreCallValidateCmdPipelineBarrier(layer_data *device_data, GLOBAL_CB_NODE *cb_state, VkCommandBuffer commandBuffer, 830603122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, 830703122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers, 830803122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers, 830903122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers) { 831003122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski bool skip = false; 831103122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski skip |= ValidateStageMasksAgainstQueueCapabilities(device_data, cb_state, srcStageMask, dstStageMask, "vkCmdPipelineBarrier", 831203122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski VALIDATION_ERROR_02513); 831303122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski skip |= ValidateCmd(device_data, cb_state, CMD_PIPELINEBARRIER, "vkCmdPipelineBarrier()"); 831403122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski skip |= ValidateStageMaskGsTsEnables(device_data, srcStageMask, "vkCmdPipelineBarrier()", VALIDATION_ERROR_00265, 831503122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski VALIDATION_ERROR_00267); 831603122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski skip |= ValidateStageMaskGsTsEnables(device_data, dstStageMask, "vkCmdPipelineBarrier()", VALIDATION_ERROR_00266, 831703122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski VALIDATION_ERROR_00268); 831803122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski UpdateCmdBufferLastCmd(cb_state, CMD_PIPELINEBARRIER); 8319e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski skip |= ValidateImageLayouts(device_data, commandBuffer, imageMemoryBarrierCount, pImageMemoryBarriers); 8320e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski if (!skip) { 8321e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski TransitionImageLayouts(device_data, commandBuffer, imageMemoryBarrierCount, pImageMemoryBarriers); 8322e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski } 832303122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski skip |= ValidateBarriers("vkCmdPipelineBarrier()", commandBuffer, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, 832403122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers); 832503122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski return skip; 832603122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski} 832703122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski 8328d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdPipelineBarrier(VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask, 8329d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags, 8330d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers, 8331d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers, 8332d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers) { 8333d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski bool skip = false; 833456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 8335b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 83369a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer); 8337d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski if (cb_state) { 833803122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski skip |= PreCallValidateCmdPipelineBarrier(dev_data, cb_state, commandBuffer, srcStageMask, dstStageMask, 833903122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, 834003122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers); 83415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8342b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 8343d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski if (!skip) 83444a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, memoryBarrierCount, 83454a0754042cf090e131e9e769d8a3633c228625beChris Forbes pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, 83464a0754042cf090e131e9e769d8a3633c228625beChris Forbes imageMemoryBarrierCount, pImageMemoryBarriers); 83475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 83485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8349d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentinebool setQueryState(VkQueue queue, VkCommandBuffer commandBuffer, QueryObject object, bool value) { 835056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 83519a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 8352d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine if (pCB) { 8353d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine pCB->queryToStateMap[object] = value; 8354d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 8355d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine auto queue_data = dev_data->queueMap.find(queue); 8356d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine if (queue_data != dev_data->queueMap.end()) { 8357d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine queue_data->second.queryToStateMap[object] = value; 8358d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 8359d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine return false; 8360d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine} 8361d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine 8362bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBeginQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t slot, VkFlags flags) { 836383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 836456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 8365b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 83669a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 83675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 83685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis QueryObject query = {queryPool, slot}; 83695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->activeQueries.insert(query); 83705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!pCB->startedQueries.count(query)) { 83715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->startedQueries.insert(query); 83725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 837329f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_BEGINQUERY, "vkCmdBeginQuery()"); 83741ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_BEGINQUERY); 83759a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis addCommandBufferBinding(&GetQueryPoolNode(dev_data, queryPool)->cb_bindings, 8376ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis {reinterpret_cast<uint64_t &>(queryPool), VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT}, pCB); 83775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8378b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 8379cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.CmdBeginQuery(commandBuffer, queryPool, slot, flags); 83805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 83815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 838289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdEndQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t slot) { 8383946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski bool skip = false; 838456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 8385b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 8386946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer); 8387946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (cb_state) { 83885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis QueryObject query = {queryPool, slot}; 8389946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (!cb_state->activeQueries.count(query)) { 8390946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= 83915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 83929bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt VALIDATION_ERROR_01041, "DS", "Ending a query before it was started: queryPool 0x%" PRIx64 ", index %d. %s", 83939bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt (uint64_t)(queryPool), slot, validation_error_map[VALIDATION_ERROR_01041]); 83945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 8395946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->activeQueries.erase(query); 83965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8397946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski std::function<bool(VkQueue)> query_update = std::bind(setQueryState, std::placeholders::_1, commandBuffer, query, true); 8398946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->queryUpdates.push_back(query_update); 8399946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ValidateCmd(dev_data, cb_state, CMD_ENDQUERY, "VkCmdEndQuery()"); 8400946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski UpdateCmdBufferLastCmd(cb_state, CMD_ENDQUERY); 84019a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis addCommandBufferBinding(&GetQueryPoolNode(dev_data, queryPool)->cb_bindings, 8402946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski {reinterpret_cast<uint64_t &>(queryPool), VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT}, cb_state); 84035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8404b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 8405946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdEndQuery(commandBuffer, queryPool, slot); 84065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 84075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8408bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdResetQueryPool(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, 8409bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski uint32_t queryCount) { 8410946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski bool skip = false; 841156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 8412b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 8413946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer); 8414946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (cb_state) { 84155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < queryCount; i++) { 84165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis QueryObject query = {queryPool, firstQuery + i}; 8417946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->waitedEventsBeforeQueryReset[query] = cb_state->waitedEvents; 8418946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski std::function<bool(VkQueue)> query_update = 8419946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski std::bind(setQueryState, std::placeholders::_1, commandBuffer, query, false); 8420946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->queryUpdates.push_back(query_update); 8421946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski } 8422946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ValidateCmd(dev_data, cb_state, CMD_RESETQUERYPOOL, "VkCmdResetQueryPool()"); 8423946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski UpdateCmdBufferLastCmd(cb_state, CMD_RESETQUERYPOOL); 8424946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= insideRenderPass(dev_data, cb_state, "vkCmdResetQueryPool()", VALIDATION_ERROR_01025); 84259a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis addCommandBufferBinding(&GetQueryPoolNode(dev_data, queryPool)->cb_bindings, 8426946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski {reinterpret_cast<uint64_t &>(queryPool), VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT}, cb_state); 84275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8428b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 8429946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdResetQueryPool(commandBuffer, queryPool, firstQuery, queryCount); 84305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 84315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8432d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentinebool validateQuery(VkQueue queue, GLOBAL_CB_NODE *pCB, VkQueryPool queryPool, uint32_t queryCount, uint32_t firstQuery) { 8433d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine bool skip_call = false; 843456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(pCB->commandBuffer), layer_data_map); 8435d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine auto queue_data = dev_data->queueMap.find(queue); 8436cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (queue_data == dev_data->queueMap.end()) return false; 8437d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine for (uint32_t i = 0; i < queryCount; i++) { 8438d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine QueryObject query = {queryPool, firstQuery + i}; 8439d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine auto query_data = queue_data->second.queryToStateMap.find(query); 8440d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine bool fail = false; 8441d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine if (query_data != queue_data->second.queryToStateMap.end()) { 8442d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine if (!query_data->second) { 8443d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine fail = true; 8444d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 8445d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } else { 8446d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine auto global_query_data = dev_data->queryToStateMap.find(query); 8447d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine if (global_query_data != dev_data->queryToStateMap.end()) { 8448d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine if (!global_query_data->second) { 8449d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine fail = true; 8450d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 8451d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } else { 8452d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine fail = true; 8453d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 8454d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 8455d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine if (fail) { 8456d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 8457d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine DRAWSTATE_INVALID_QUERY, "DS", 8458d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine "Requesting a copy from query to buffer with invalid query: queryPool 0x%" PRIx64 ", index %d", 8459d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine reinterpret_cast<uint64_t &>(queryPool), firstQuery + i); 8460d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 8461d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 8462d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine return skip_call; 8463d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine} 8464d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine 8465bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdCopyQueryPoolResults(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, 8466bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski uint32_t queryCount, VkBuffer dstBuffer, VkDeviceSize dstOffset, 8467bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDeviceSize stride, VkQueryResultFlags flags) { 8468946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski bool skip = false; 846956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 8470b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 8471ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis 84729a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, commandBuffer); 84739a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto dst_buff_state = GetBufferState(dev_data, dstBuffer); 84745cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis if (cb_node && dst_buff_state) { 8475946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ValidateMemoryIsBoundToBuffer(dev_data, dst_buff_state, "vkCmdCopyQueryPoolResults()", VALIDATION_ERROR_02526); 8476ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis // Update bindings between buffer and cmd buffer 84775cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis AddCommandBufferBindingBuffer(dev_data, cb_node, dst_buff_state); 8478ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis // Validate that DST buffer has correct usage flags set 8479946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ValidateBufferUsageFlags(dev_data, dst_buff_state, VK_BUFFER_USAGE_TRANSFER_DST_BIT, true, VALIDATION_ERROR_01066, 8480946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "vkCmdCopyQueryPoolResults()", "VK_BUFFER_USAGE_TRANSFER_DST_BIT"); 8481e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves std::function<bool()> function = [=]() { 84825cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis SetBufferMemoryValid(dev_data, dst_buff_state, true); 8483e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves return false; 84845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis }; 84859f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis cb_node->validate_functions.push_back(function); 8486946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski std::function<bool(VkQueue)> query_update = 8487ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis std::bind(validateQuery, std::placeholders::_1, cb_node, queryPool, queryCount, firstQuery); 8488946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_node->queryUpdates.push_back(query_update); 8489946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ValidateCmd(dev_data, cb_node, CMD_COPYQUERYPOOLRESULTS, "vkCmdCopyQueryPoolResults()"); 8490ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski UpdateCmdBufferLastCmd(cb_node, CMD_COPYQUERYPOOLRESULTS); 8491946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= insideRenderPass(dev_data, cb_node, "vkCmdCopyQueryPoolResults()", VALIDATION_ERROR_01074); 84929a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis addCommandBufferBinding(&GetQueryPoolNode(dev_data, queryPool)->cb_bindings, 8493ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis {reinterpret_cast<uint64_t &>(queryPool), VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT}, cb_node); 8494ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } else { 8495ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis assert(0); 84965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8497b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 8498946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (!skip) 84994a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdCopyQueryPoolResults(commandBuffer, queryPool, firstQuery, queryCount, dstBuffer, dstOffset, 85004a0754042cf090e131e9e769d8a3633c228625beChris Forbes stride, flags); 85015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 85025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8503bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdPushConstants(VkCommandBuffer commandBuffer, VkPipelineLayout layout, VkShaderStageFlags stageFlags, 8504bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski uint32_t offset, uint32_t size, const void *pValues) { 8505946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski bool skip = false; 850656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 8507b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 8508946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer); 8509946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (cb_state) { 8510946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ValidateCmd(dev_data, cb_state, CMD_PUSHCONSTANTS, "vkCmdPushConstants()"); 8511946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski UpdateCmdBufferLastCmd(cb_state, CMD_PUSHCONSTANTS); 85125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8513946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= validatePushConstantRange(dev_data, offset, size, "vkCmdPushConstants()"); 85149e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz if (0 == stageFlags) { 8515946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 8516946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski VALIDATION_ERROR_00996, "DS", "vkCmdPushConstants() call has no stageFlags set. %s", 8517946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski validation_error_map[VALIDATION_ERROR_00996]); 85189e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 85199e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz 8520a95cb74c9d0947ab3821b15e1289755286ea78eeKarl Schultz // Check if push constant update is within any of the ranges with the same stage flags specified in pipeline layout. 8521c2a5a36d03bbe52f5854a5884346e4a84115e259Tobin Ehlis auto pipeline_layout = getPipelineLayout(dev_data, layout); 852215a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis // Coalesce adjacent/overlapping pipeline ranges before checking to see if incoming range is 852315a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis // contained in the pipeline ranges. 852415a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis // Build a {start, end} span list for ranges with matching stage flags. 852515a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis const auto &ranges = pipeline_layout->push_constant_ranges; 852615a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis struct span { 852715a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis uint32_t start; 852815a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis uint32_t end; 852915a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis }; 853015a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis std::vector<span> spans; 853115a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis spans.reserve(ranges.size()); 853215a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis for (const auto &iter : ranges) { 853315a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis if (iter.stageFlags == stageFlags) { 853415a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis spans.push_back({iter.offset, iter.offset + iter.size}); 853515a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis } 853615a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis } 853715a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis if (spans.size() == 0) { 853815a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis // There were no ranges that matched the stageFlags. 8539946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 8540946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski VALIDATION_ERROR_00988, "DS", "vkCmdPushConstants() stageFlags = 0x%" PRIx32 8541946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski " do not match " 8542946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "the stageFlags in any of the ranges in pipeline layout 0x%" PRIx64 ". %s", 8543946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski (uint32_t)stageFlags, (uint64_t)layout, validation_error_map[VALIDATION_ERROR_00988]); 85449e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } else { 854515a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis // Sort span list by start value. 854615a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis struct comparer { 854715a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis bool operator()(struct span i, struct span j) { return i.start < j.start; } 854815a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis } my_comparer; 854915a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis std::sort(spans.begin(), spans.end(), my_comparer); 855015a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis 855115a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis // Examine two spans at a time. 855215a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis std::vector<span>::iterator current = spans.begin(); 855315a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis std::vector<span>::iterator next = current + 1; 855415a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis while (next != spans.end()) { 855515a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis if (current->end < next->start) { 855615a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis // There is a gap; cannot coalesce. Move to the next two spans. 855715a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis ++current; 855815a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis ++next; 855915a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis } else { 856015a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis // Coalesce the two spans. The start of the next span 856115a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis // is within the current span, so pick the larger of 856215a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis // the end values to extend the current span. 856315a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis // Then delete the next span and set next to the span after it. 856415a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis current->end = max(current->end, next->end); 856515a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis next = spans.erase(next); 85669e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 85679e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 8568a95cb74c9d0947ab3821b15e1289755286ea78eeKarl Schultz 856915a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis // Now we can check if the incoming range is within any of the spans. 857015a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis bool contained_in_a_range = false; 857115a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis for (uint32_t i = 0; i < spans.size(); ++i) { 857215a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis if ((offset >= spans[i].start) && ((uint64_t)offset + (uint64_t)size <= (uint64_t)spans[i].end)) { 857315a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis contained_in_a_range = true; 857415a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis break; 8575a95cb74c9d0947ab3821b15e1289755286ea78eeKarl Schultz } 85769e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 857715a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis if (!contained_in_a_range) { 8578946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= log_msg( 8579946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 8580946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski VALIDATION_ERROR_00988, "DS", "vkCmdPushConstants() Push constant range [%d, %d) with stageFlags = 0x%" PRIx32 8581946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski " not within flag-matching ranges in pipeline layout 0x%" PRIx64 ". %s", 8582946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski offset, offset + size, (uint32_t)stageFlags, (uint64_t)layout, validation_error_map[VALIDATION_ERROR_00988]); 858315a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis } 85845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8585b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 8586946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdPushConstants(commandBuffer, layout, stageFlags, offset, size, pValues); 85875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 85885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8589bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdWriteTimestamp(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, 8590bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkQueryPool queryPool, uint32_t slot) { 8591946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski bool skip = false; 859256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 8593b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 8594946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer); 8595946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (cb_state) { 85965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis QueryObject query = {queryPool, slot}; 8597946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski std::function<bool(VkQueue)> query_update = std::bind(setQueryState, std::placeholders::_1, commandBuffer, query, true); 8598946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->queryUpdates.push_back(query_update); 8599946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ValidateCmd(dev_data, cb_state, CMD_WRITETIMESTAMP, "vkCmdWriteTimestamp()"); 8600946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski UpdateCmdBufferLastCmd(cb_state, CMD_WRITETIMESTAMP); 86015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8602b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 8603946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdWriteTimestamp(commandBuffer, pipelineStage, queryPool, slot); 86045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 86055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 86066600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinskistatic bool MatchUsage(layer_data *dev_data, uint32_t count, const VkAttachmentReference *attachments, 86079bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt const VkFramebufferCreateInfo *fbci, VkImageUsageFlagBits usage_flag, 86089bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt UNIQUE_VALIDATION_ERROR_CODE error_code) { 8609946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski bool skip = false; 86106600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski 86116600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski for (uint32_t attach = 0; attach < count; attach++) { 86126600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski if (attachments[attach].attachment != VK_ATTACHMENT_UNUSED) { 86136600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski // Attachment counts are verified elsewhere, but prevent an invalid access 86146600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski if (attachments[attach].attachment < fbci->attachmentCount) { 86156600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski const VkImageView *image_view = &fbci->pAttachments[attachments[attach].attachment]; 86169a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto view_state = GetImageViewState(dev_data, *image_view); 861779fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis if (view_state) { 86189a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis const VkImageCreateInfo *ici = &GetImageState(dev_data, view_state->create_info.image)->createInfo; 86196600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski if (ici != nullptr) { 86206600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski if ((ici->usage & usage_flag) == 0) { 8621946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 8622946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski __LINE__, error_code, "DS", 8623946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "vkCreateFramebuffer: Framebuffer Attachment (%d) conflicts with the image's " 8624946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "IMAGE_USAGE flags (%s). %s", 8625946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski attachments[attach].attachment, string_VkImageUsageFlagBits(usage_flag), 8626946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski validation_error_map[error_code]); 86276600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski } 86286600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski } 86296600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski } 86306600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski } 86316600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski } 86326600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski } 8633946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski return skip; 86346600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski} 86356600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski 8636d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis// Validate VkFramebufferCreateInfo which includes: 8637d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis// 1. attachmentCount equals renderPass attachmentCount 86385ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 2. corresponding framebuffer and renderpass attachments have matching formats 86395ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 3. corresponding framebuffer and renderpass attachments have matching sample counts 86405ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 4. fb attachments only have a single mip level 86415ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 5. fb attachment dimensions are each at least as large as the fb 86425ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 6. fb attachments use idenity swizzle 86435ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 7. fb attachments used by renderPass for color/input/ds have correct usage bit set 86446fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis// 8. fb dimensions are within physical device limits 8645d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlisstatic bool ValidateFramebufferCreateInfo(layer_data *dev_data, const VkFramebufferCreateInfo *pCreateInfo) { 86466600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski bool skip_call = false; 86476600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski 86489a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto rp_state = GetRenderPassState(dev_data, pCreateInfo->renderPass); 8649127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis if (rp_state) { 8650127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis const VkRenderPassCreateInfo *rpci = rp_state->createInfo.ptr(); 8651d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis if (rpci->attachmentCount != pCreateInfo->attachmentCount) { 8652d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis skip_call |= log_msg( 8653d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT, 86549bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt reinterpret_cast<const uint64_t &>(pCreateInfo->renderPass), __LINE__, VALIDATION_ERROR_00404, "DS", 8655d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis "vkCreateFramebuffer(): VkFramebufferCreateInfo attachmentCount of %u does not match attachmentCount of %u of " 86569bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "renderPass (0x%" PRIxLEAST64 ") being used to create Framebuffer. %s", 86579bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt pCreateInfo->attachmentCount, rpci->attachmentCount, reinterpret_cast<const uint64_t &>(pCreateInfo->renderPass), 86589bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt validation_error_map[VALIDATION_ERROR_00404]); 86595ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis } else { 866041ebcb6b517b1de5ae456d46d866f5e84a96a2c5Tobin Ehlis // attachmentCounts match, so make sure corresponding attachment details line up 86615ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis const VkImageView *image_views = pCreateInfo->pAttachments; 86625ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) { 86639a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto view_state = GetImageViewState(dev_data, image_views[i]); 866412d5600c2f9e32343016fd944432ba95df370797Tobin Ehlis auto &ivci = view_state->create_info; 866579fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis if (ivci.format != rpci->pAttachments[i].format) { 86665ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis skip_call |= log_msg( 86675ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT, 86689bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt reinterpret_cast<const uint64_t &>(pCreateInfo->renderPass), __LINE__, VALIDATION_ERROR_00408, "DS", 86699bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "vkCreateFramebuffer(): VkFramebufferCreateInfo attachment #%u has format of %s that does not match " 86709bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "the format of " 86719bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "%s used by the corresponding attachment for renderPass (0x%" PRIxLEAST64 "). %s", 867279fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis i, string_VkFormat(ivci.format), string_VkFormat(rpci->pAttachments[i].format), 86739bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt reinterpret_cast<const uint64_t &>(pCreateInfo->renderPass), validation_error_map[VALIDATION_ERROR_00408]); 86745ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis } 86759a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis const VkImageCreateInfo *ici = &GetImageState(dev_data, ivci.image)->createInfo; 86765ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis if (ici->samples != rpci->pAttachments[i].samples) { 867741ebcb6b517b1de5ae456d46d866f5e84a96a2c5Tobin Ehlis skip_call |= log_msg( 867841ebcb6b517b1de5ae456d46d866f5e84a96a2c5Tobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT, 86799bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt reinterpret_cast<const uint64_t &>(pCreateInfo->renderPass), __LINE__, VALIDATION_ERROR_00409, "DS", 86809bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "vkCreateFramebuffer(): VkFramebufferCreateInfo attachment #%u has %s samples that do not match " 86819bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "the %s samples used by the corresponding attachment for renderPass (0x%" PRIxLEAST64 "). %s", 868241ebcb6b517b1de5ae456d46d866f5e84a96a2c5Tobin Ehlis i, string_VkSampleCountFlagBits(ici->samples), string_VkSampleCountFlagBits(rpci->pAttachments[i].samples), 86839bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt reinterpret_cast<const uint64_t &>(pCreateInfo->renderPass), validation_error_map[VALIDATION_ERROR_00409]); 86845ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis } 86855ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis // Verify that view only has a single mip level 868679fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis if (ivci.subresourceRange.levelCount != 1) { 86879bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt skip_call |= 86889bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 86899bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt VALIDATION_ERROR_00411, "DS", 86909bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "vkCreateFramebuffer(): VkFramebufferCreateInfo attachment #%u has mip levelCount of %u " 86919bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "but only a single mip level (levelCount == 1) is allowed when creating a Framebuffer. %s", 86929bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt i, ivci.subresourceRange.levelCount, validation_error_map[VALIDATION_ERROR_00411]); 86935ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis } 869479fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis const uint32_t mip_level = ivci.subresourceRange.baseMipLevel; 8695aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis uint32_t mip_width = max(1u, ici->extent.width >> mip_level); 8696aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis uint32_t mip_height = max(1u, ici->extent.height >> mip_level); 869779fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis if ((ivci.subresourceRange.layerCount < pCreateInfo->layers) || (mip_width < pCreateInfo->width) || 8698aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis (mip_height < pCreateInfo->height)) { 8699aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis skip_call |= 87006fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 8701aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis DRAWSTATE_INVALID_FRAMEBUFFER_CREATE_INFO, "DS", 8702aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis "vkCreateFramebuffer(): VkFramebufferCreateInfo attachment #%u mip level %u has dimensions smaller " 8703aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis "than the corresponding " 8704aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis "framebuffer dimensions. Attachment dimensions must be at least as large. Here are the respective " 8705aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis "dimensions for " 8706aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis "attachment #%u, framebuffer:\n" 8707aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis "width: %u, %u\n" 8708aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis "height: %u, %u\n" 8709aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis "layerCount: %u, %u\n", 871079fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis i, ivci.subresourceRange.baseMipLevel, i, mip_width, pCreateInfo->width, mip_height, 871179fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis pCreateInfo->height, ivci.subresourceRange.layerCount, pCreateInfo->layers); 87125ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis } 871379fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis if (((ivci.components.r != VK_COMPONENT_SWIZZLE_IDENTITY) && (ivci.components.r != VK_COMPONENT_SWIZZLE_R)) || 871479fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis ((ivci.components.g != VK_COMPONENT_SWIZZLE_IDENTITY) && (ivci.components.g != VK_COMPONENT_SWIZZLE_G)) || 871579fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis ((ivci.components.b != VK_COMPONENT_SWIZZLE_IDENTITY) && (ivci.components.b != VK_COMPONENT_SWIZZLE_B)) || 871679fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis ((ivci.components.a != VK_COMPONENT_SWIZZLE_IDENTITY) && (ivci.components.a != VK_COMPONENT_SWIZZLE_A))) { 8717da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis skip_call |= log_msg( 87186fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 87199bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt VALIDATION_ERROR_00412, "DS", 8720da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis "vkCreateFramebuffer(): VkFramebufferCreateInfo attachment #%u has non-identy swizzle. All framebuffer " 8721da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis "attachments must have been created with the identity swizzle. Here are the actual swizzle values:\n" 8722da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis "r swizzle = %s\n" 8723da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis "g swizzle = %s\n" 8724da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis "b swizzle = %s\n" 87259bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "a swizzle = %s\n" 87269bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "%s", 872779fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis i, string_VkComponentSwizzle(ivci.components.r), string_VkComponentSwizzle(ivci.components.g), 87289bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt string_VkComponentSwizzle(ivci.components.b), string_VkComponentSwizzle(ivci.components.a), 87299bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt validation_error_map[VALIDATION_ERROR_00412]); 87305ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis } 87315ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis } 8732d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis } 87335ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis // Verify correct attachment usage flags 87346600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski for (uint32_t subpass = 0; subpass < rpci->subpassCount; subpass++) { 87356600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski // Verify input attachments: 87369bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt skip_call |= 87379bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt MatchUsage(dev_data, rpci->pSubpasses[subpass].inputAttachmentCount, rpci->pSubpasses[subpass].pInputAttachments, 87389bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt pCreateInfo, VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT, VALIDATION_ERROR_00407); 87396600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski // Verify color attachments: 87409bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt skip_call |= 87419bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt MatchUsage(dev_data, rpci->pSubpasses[subpass].colorAttachmentCount, rpci->pSubpasses[subpass].pColorAttachments, 87429bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt pCreateInfo, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VALIDATION_ERROR_00405); 87436600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski // Verify depth/stencil attachments: 87446600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski if (rpci->pSubpasses[subpass].pDepthStencilAttachment != nullptr) { 87456600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski skip_call |= MatchUsage(dev_data, 1, rpci->pSubpasses[subpass].pDepthStencilAttachment, pCreateInfo, 87469bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VALIDATION_ERROR_00406); 87476600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski } 87486600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski } 87496600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski } 87506fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis // Verify FB dimensions are within physical device limits 87519bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt if (pCreateInfo->width > dev_data->phys_dev_properties.properties.limits.maxFramebufferWidth) { 87526fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 87539bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt VALIDATION_ERROR_00413, "DS", 87549bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "vkCreateFramebuffer(): Requested VkFramebufferCreateInfo width exceeds physical device limits. " 87559bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "Requested width: %u, device max: %u\n" 87569bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "%s", 87576fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis pCreateInfo->width, dev_data->phys_dev_properties.properties.limits.maxFramebufferWidth, 87589bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt validation_error_map[VALIDATION_ERROR_00413]); 87599bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt } 87609bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt if (pCreateInfo->height > dev_data->phys_dev_properties.properties.limits.maxFramebufferHeight) { 87619bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 87629bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt VALIDATION_ERROR_00414, "DS", 87639bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "vkCreateFramebuffer(): Requested VkFramebufferCreateInfo height exceeds physical device limits. " 87649bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "Requested height: %u, device max: %u\n" 87659bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "%s", 87666fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis pCreateInfo->height, dev_data->phys_dev_properties.properties.limits.maxFramebufferHeight, 87679bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt validation_error_map[VALIDATION_ERROR_00414]); 87689bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt } 87699bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt if (pCreateInfo->layers > dev_data->phys_dev_properties.properties.limits.maxFramebufferLayers) { 87709bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 87719bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt VALIDATION_ERROR_00415, "DS", 87729bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "vkCreateFramebuffer(): Requested VkFramebufferCreateInfo layers exceeds physical device limits. " 87739bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "Requested layers: %u, device max: %u\n" 87749bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "%s", 87759bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt pCreateInfo->layers, dev_data->phys_dev_properties.properties.limits.maxFramebufferLayers, 87769bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt validation_error_map[VALIDATION_ERROR_00415]); 87776fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis } 87786600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski return skip_call; 87796600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski} 87806600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski 878164c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis// Validate VkFramebufferCreateInfo state prior to calling down chain to create Framebuffer object 878264c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis// Return true if an error is encountered and callback returns true to skip call down chain 878364c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis// false indicates that call down chain should proceed 878464c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlisstatic bool PreCallValidateCreateFramebuffer(layer_data *dev_data, const VkFramebufferCreateInfo *pCreateInfo) { 878564c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis // TODO : Verify that renderPass FB is created with is compatible with FB 878664c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis bool skip_call = false; 8787d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis skip_call |= ValidateFramebufferCreateInfo(dev_data, pCreateInfo); 878864c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis return skip_call; 878964c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis} 879064c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis 879154e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis// CreateFramebuffer state has been validated and call down chain completed so record new framebuffer object 879254e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlisstatic void PostCallRecordCreateFramebuffer(layer_data *dev_data, const VkFramebufferCreateInfo *pCreateInfo, VkFramebuffer fb) { 879354e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis // Shadow create info and store in map 8794c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis std::unique_ptr<FRAMEBUFFER_STATE> fb_state( 8795c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis new FRAMEBUFFER_STATE(fb, pCreateInfo, dev_data->renderPassMap[pCreateInfo->renderPass]->createInfo.ptr())); 879676f04ca0e692f9f15d5ef7e0c658c24d11f34ebcTobin Ehlis 879754e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) { 879854e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis VkImageView view = pCreateInfo->pAttachments[i]; 87999a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto view_state = GetImageViewState(dev_data, view); 880079fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis if (!view_state) { 880154e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis continue; 880254e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis } 880354e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis MT_FB_ATTACHMENT_INFO fb_info; 88049a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis fb_info.mem = GetImageState(dev_data, view_state->create_info.image)->binding.mem; 8805883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis fb_info.view_state = view_state; 880679fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis fb_info.image = view_state->create_info.image; 8807c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis fb_state->attachments.push_back(fb_info); 880854e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis } 8809c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis dev_data->frameBufferMap[fb] = std::move(fb_state); 881054e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis} 881154e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis 881289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateFramebuffer(VkDevice device, const VkFramebufferCreateInfo *pCreateInfo, 8813bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkFramebuffer *pFramebuffer) { 881456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 881564c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 881664c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis bool skip_call = PreCallValidateCreateFramebuffer(dev_data, pCreateInfo); 881764c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis lock.unlock(); 881864c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis 8819cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip_call) return VK_ERROR_VALIDATION_FAILED_EXT; 882064c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis 88214a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateFramebuffer(device, pCreateInfo, pAllocator, pFramebuffer); 88226600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski 88235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 882464c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis lock.lock(); 882554e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis PostCallRecordCreateFramebuffer(dev_data, pCreateInfo, *pFramebuffer); 882654e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis lock.unlock(); 88275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 88285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 88295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 88305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8831e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool FindDependency(const int index, const int dependent, const std::vector<DAGNode> &subpass_to_node, 8832e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves std::unordered_set<uint32_t> &processed_nodes) { 88335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // If we have already checked this node we have not found a dependency path so return false. 8834cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (processed_nodes.count(index)) return false; 88355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis processed_nodes.insert(index); 88365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const DAGNode &node = subpass_to_node[index]; 88375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Look for a dependency path. If one exists return true else recurse on the previous nodes. 8838593f84b63934f07483e5e5a20fd352df8ab4f8c9Bruce Dawson if (std::find(node.prev.begin(), node.prev.end(), static_cast<uint32_t>(dependent)) == node.prev.end()) { 88395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto elem : node.prev) { 8840cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (FindDependency(elem, dependent, subpass_to_node, processed_nodes)) return true; 88415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 88425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 8843e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves return true; 88445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8845e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves return false; 88465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 88475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 88488860b85a52096f9f9b28616bc37feed505497a54Chris Forbesstatic bool CheckDependencyExists(const layer_data *dev_data, const int subpass, const std::vector<uint32_t> &dependent_subpasses, 8849e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves const std::vector<DAGNode> &subpass_to_node, bool &skip_call) { 8850e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool result = true; 88515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Loop through all subpasses that share the same attachment and make sure a dependency exists 88525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t k = 0; k < dependent_subpasses.size(); ++k) { 8853cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (static_cast<uint32_t>(subpass) == dependent_subpasses[k]) continue; 88545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const DAGNode &node = subpass_to_node[subpass]; 88555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Check for a specified dependency between the two nodes. If one exists we are done. 88565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto prev_elem = std::find(node.prev.begin(), node.prev.end(), dependent_subpasses[k]); 88575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto next_elem = std::find(node.next.begin(), node.next.end(), dependent_subpasses[k]); 88585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (prev_elem == node.prev.end() && next_elem == node.next.end()) { 88597655cb8b5eb52badee0b011729a05afa36316d69Jan-Harald Fredriksen // If no dependency exits an implicit dependency still might. If not, throw an error. 88605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_set<uint32_t> processed_nodes; 88617655cb8b5eb52badee0b011729a05afa36316d69Jan-Harald Fredriksen if (!(FindDependency(subpass, dependent_subpasses[k], subpass_to_node, processed_nodes) || 8862bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski FindDependency(dependent_subpasses[k], subpass, subpass_to_node, processed_nodes))) { 88638860b85a52096f9f9b28616bc37feed505497a54Chris Forbes skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 88645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS", 88655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis "A dependency between subpasses %d and %d must exist but one is not specified.", subpass, 88665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dependent_subpasses[k]); 8867e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves result = false; 88685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 88695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 88705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 88715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 88725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 88735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 88748860b85a52096f9f9b28616bc37feed505497a54Chris Forbesstatic bool CheckPreserved(const layer_data *dev_data, const VkRenderPassCreateInfo *pCreateInfo, const int index, 8875e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves const uint32_t attachment, const std::vector<DAGNode> &subpass_to_node, int depth, bool &skip_call) { 88765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const DAGNode &node = subpass_to_node[index]; 88775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // If this node writes to the attachment return true as next nodes need to preserve the attachment. 88785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[index]; 88795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) { 8880cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (attachment == subpass.pColorAttachments[j].attachment) return true; 88815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8882a4ea781e8fff70c9db0bedad7fcb6bba08e35da7Tony Barbour for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) { 8883a4ea781e8fff70c9db0bedad7fcb6bba08e35da7Tony Barbour if (attachment == subpass.pInputAttachments[j].attachment) return true; 8884a4ea781e8fff70c9db0bedad7fcb6bba08e35da7Tony Barbour } 88855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) { 8886cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (attachment == subpass.pDepthStencilAttachment->attachment) return true; 88875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8888e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool result = false; 88895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Loop through previous nodes and see if any of them write to the attachment. 88905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto elem : node.prev) { 88918860b85a52096f9f9b28616bc37feed505497a54Chris Forbes result |= CheckPreserved(dev_data, pCreateInfo, elem, attachment, subpass_to_node, depth + 1, skip_call); 88925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 88935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // If the attachment was written to by a previous node than this node needs to preserve it. 88945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (result && depth > 0) { 8895e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool has_preserved = false; 88965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t j = 0; j < subpass.preserveAttachmentCount; ++j) { 88975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (subpass.pPreserveAttachments[j] == attachment) { 8898e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves has_preserved = true; 88995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis break; 89005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 89015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8902e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves if (!has_preserved) { 89035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis skip_call |= 89048860b85a52096f9f9b28616bc37feed505497a54Chris Forbes log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 89055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis DRAWSTATE_INVALID_RENDERPASS, "DS", 89065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis "Attachment %d is used by a later subpass and must be preserved in subpass %d.", attachment, index); 89075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 89085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 89095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 89105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 89115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8912cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskitemplate <class T> 8913cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskibool isRangeOverlapping(T offset1, T size1, T offset2, T size2) { 89145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return (((offset1 + size1) > offset2) && ((offset1 + size1) < (offset2 + size2))) || 89155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis ((offset1 > offset2) && (offset1 < (offset2 + size2))); 89165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 89175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 89185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisbool isRegionOverlapping(VkImageSubresourceRange range1, VkImageSubresourceRange range2) { 89195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return (isRangeOverlapping(range1.baseMipLevel, range1.levelCount, range2.baseMipLevel, range2.levelCount) && 89205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis isRangeOverlapping(range1.baseArrayLayer, range1.layerCount, range2.baseArrayLayer, range2.layerCount)); 89215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 89225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8923c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlisstatic bool ValidateDependencies(const layer_data *dev_data, FRAMEBUFFER_STATE const *framebuffer, 8924127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis RENDER_PASS_STATE const *renderPass) { 8925e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool skip_call = false; 8926fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes auto const pFramebufferInfo = framebuffer->createInfo.ptr(); 8927fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes auto const pCreateInfo = renderPass->createInfo.ptr(); 8928bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto const &subpass_to_node = renderPass->subpassToNode; 89295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::vector<std::vector<uint32_t>> output_attachment_to_subpass(pCreateInfo->attachmentCount); 89305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::vector<std::vector<uint32_t>> input_attachment_to_subpass(pCreateInfo->attachmentCount); 89315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::vector<std::vector<uint32_t>> overlapping_attachments(pCreateInfo->attachmentCount); 89325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Find overlapping attachments 89335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) { 89345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t j = i + 1; j < pCreateInfo->attachmentCount; ++j) { 89355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkImageView viewi = pFramebufferInfo->pAttachments[i]; 89365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkImageView viewj = pFramebufferInfo->pAttachments[j]; 89375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (viewi == viewj) { 89385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis overlapping_attachments[i].push_back(j); 89395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis overlapping_attachments[j].push_back(i); 89405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis continue; 89415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 89429a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto view_state_i = GetImageViewState(dev_data, viewi); 89439a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto view_state_j = GetImageViewState(dev_data, viewj); 894479fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis if (!view_state_i || !view_state_j) { 89455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis continue; 89465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 894779fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis auto view_ci_i = view_state_i->create_info; 894879fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis auto view_ci_j = view_state_j->create_info; 894979fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis if (view_ci_i.image == view_ci_j.image && isRegionOverlapping(view_ci_i.subresourceRange, view_ci_j.subresourceRange)) { 89505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis overlapping_attachments[i].push_back(j); 89515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis overlapping_attachments[j].push_back(i); 89525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis continue; 89535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 89549a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_data_i = GetImageState(dev_data, view_ci_i.image); 89559a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_data_j = GetImageState(dev_data, view_ci_j.image); 89566d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis if (!image_data_i || !image_data_j) { 89575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis continue; 89585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8959e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis if (image_data_i->binding.mem == image_data_j->binding.mem && 8960e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis isRangeOverlapping(image_data_i->binding.offset, image_data_i->binding.size, image_data_j->binding.offset, 8961e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis image_data_j->binding.size)) { 89625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis overlapping_attachments[i].push_back(j); 89635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis overlapping_attachments[j].push_back(i); 89645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 89655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 89665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 89675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < overlapping_attachments.size(); ++i) { 89685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t attachment = i; 89695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto other_attachment : overlapping_attachments[i]) { 89705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!(pCreateInfo->pAttachments[attachment].flags & VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT)) { 89719bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 8972cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, VALIDATION_ERROR_00324, "DS", 8973cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Attachment %d aliases attachment %d but doesn't " 8974cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "set VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT. %s", 89759bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt attachment, other_attachment, validation_error_map[VALIDATION_ERROR_00324]); 89765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 89775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!(pCreateInfo->pAttachments[other_attachment].flags & VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT)) { 89789bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 8979cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, VALIDATION_ERROR_00324, "DS", 8980cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Attachment %d aliases attachment %d but doesn't " 8981cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "set VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT. %s", 89829bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt other_attachment, attachment, validation_error_map[VALIDATION_ERROR_00324]); 89835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 89845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 89855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 89865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Find for each attachment the subpasses that use them. 89871c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young unordered_set<uint32_t> attachmentIndices; 89885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) { 89895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i]; 89901c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young attachmentIndices.clear(); 89915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) { 89925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t attachment = subpass.pInputAttachments[j].attachment; 8993cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (attachment == VK_ATTACHMENT_UNUSED) continue; 89945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis input_attachment_to_subpass[attachment].push_back(i); 89955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto overlapping_attachment : overlapping_attachments[attachment]) { 89965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis input_attachment_to_subpass[overlapping_attachment].push_back(i); 89975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 89985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 89995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) { 90005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t attachment = subpass.pColorAttachments[j].attachment; 9001cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (attachment == VK_ATTACHMENT_UNUSED) continue; 90025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis output_attachment_to_subpass[attachment].push_back(i); 90035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto overlapping_attachment : overlapping_attachments[attachment]) { 90045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis output_attachment_to_subpass[overlapping_attachment].push_back(i); 90055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 90061c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young attachmentIndices.insert(attachment); 90075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 90085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) { 90095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t attachment = subpass.pDepthStencilAttachment->attachment; 90105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis output_attachment_to_subpass[attachment].push_back(i); 90115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto overlapping_attachment : overlapping_attachments[attachment]) { 90125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis output_attachment_to_subpass[overlapping_attachment].push_back(i); 90135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 90141c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young 90151c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young if (attachmentIndices.count(attachment)) { 90161c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young skip_call |= 90178860b85a52096f9f9b28616bc37feed505497a54Chris Forbes log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 90188860b85a52096f9f9b28616bc37feed505497a54Chris Forbes DRAWSTATE_INVALID_RENDERPASS, "DS", 90198860b85a52096f9f9b28616bc37feed505497a54Chris Forbes "Cannot use same attachment (%u) as both color and depth output in same subpass (%u).", attachment, i); 90201c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young } 90215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 90225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 90235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // If there is a dependency needed make sure one exists 90245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) { 90255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i]; 90265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // If the attachment is an input then all subpasses that output must have a dependency relationship 90275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) { 902893fe72ec8460857bdb3c101095e6eb96d6171341Chris Forbes uint32_t attachment = subpass.pInputAttachments[j].attachment; 9029cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (attachment == VK_ATTACHMENT_UNUSED) continue; 90308860b85a52096f9f9b28616bc37feed505497a54Chris Forbes CheckDependencyExists(dev_data, i, output_attachment_to_subpass[attachment], subpass_to_node, skip_call); 90315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 90325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // If the attachment is an output then all subpasses that use the attachment must have a dependency relationship 90335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) { 903493fe72ec8460857bdb3c101095e6eb96d6171341Chris Forbes uint32_t attachment = subpass.pColorAttachments[j].attachment; 9035cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (attachment == VK_ATTACHMENT_UNUSED) continue; 90368860b85a52096f9f9b28616bc37feed505497a54Chris Forbes CheckDependencyExists(dev_data, i, output_attachment_to_subpass[attachment], subpass_to_node, skip_call); 90378860b85a52096f9f9b28616bc37feed505497a54Chris Forbes CheckDependencyExists(dev_data, i, input_attachment_to_subpass[attachment], subpass_to_node, skip_call); 90385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 90395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) { 90405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const uint32_t &attachment = subpass.pDepthStencilAttachment->attachment; 90418860b85a52096f9f9b28616bc37feed505497a54Chris Forbes CheckDependencyExists(dev_data, i, output_attachment_to_subpass[attachment], subpass_to_node, skip_call); 90428860b85a52096f9f9b28616bc37feed505497a54Chris Forbes CheckDependencyExists(dev_data, i, input_attachment_to_subpass[attachment], subpass_to_node, skip_call); 90435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 90445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 90455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Loop through implicit dependencies, if this pass reads make sure the attachment is preserved for all passes after it was 90465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // written. 90475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) { 90485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i]; 90495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) { 90508860b85a52096f9f9b28616bc37feed505497a54Chris Forbes CheckPreserved(dev_data, pCreateInfo, i, subpass.pInputAttachments[j].attachment, subpass_to_node, 0, skip_call); 90515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 90525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 90535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return skip_call; 90545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 90555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 90568860b85a52096f9f9b28616bc37feed505497a54Chris Forbesstatic bool CreatePassDAG(const layer_data *dev_data, VkDevice device, const VkRenderPassCreateInfo *pCreateInfo, 9057e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves std::vector<DAGNode> &subpass_to_node, std::vector<bool> &has_self_dependency) { 9058e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool skip_call = false; 90595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) { 90605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis DAGNode &subpass_node = subpass_to_node[i]; 90615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis subpass_node.pass = i; 90625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 90635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->dependencyCount; ++i) { 90645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkSubpassDependency &dependency = pCreateInfo->pDependencies[i]; 906566a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes if (dependency.srcSubpass == VK_SUBPASS_EXTERNAL || dependency.dstSubpass == VK_SUBPASS_EXTERNAL) { 906666a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes if (dependency.srcSubpass == dependency.dstSubpass) { 906766a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes skip_call |= 90688860b85a52096f9f9b28616bc37feed505497a54Chris Forbes log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 906966a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes DRAWSTATE_INVALID_RENDERPASS, "DS", "The src and dest subpasses cannot both be external."); 907066a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes } 907166a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes } else if (dependency.srcSubpass > dependency.dstSubpass) { 90728860b85a52096f9f9b28616bc37feed505497a54Chris Forbes skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 90735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis DRAWSTATE_INVALID_RENDERPASS, "DS", 90745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis "Depedency graph must be specified such that an earlier pass cannot depend on a later pass."); 90755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (dependency.srcSubpass == dependency.dstSubpass) { 90765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis has_self_dependency[dependency.srcSubpass] = true; 90775c6aacf95832467d52b2fde1130b04bef559573aChris Forbes } else { 90785c6aacf95832467d52b2fde1130b04bef559573aChris Forbes subpass_to_node[dependency.dstSubpass].prev.push_back(dependency.srcSubpass); 90795c6aacf95832467d52b2fde1130b04bef559573aChris Forbes subpass_to_node[dependency.srcSubpass].next.push_back(dependency.dstSubpass); 90805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 90815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 90825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return skip_call; 90835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 9084918c283ac4f8c604b79abd0c8b5706d2a7352a34Chris Forbes 908589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo *pCreateInfo, 9086bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkShaderModule *pShaderModule) { 908756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 9088e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool skip_call = false; 9089c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski spv_result_t spv_valid = SPV_SUCCESS; 9090b1f65702539fd041337fccd493dc6d38dd2a603eChris Forbes 9091e3443707b0f51ba7c6c458c5039dd3004c38b73eMark Lobodzinski if (!GetDisables(dev_data)->shader_validation) { 9092e3443707b0f51ba7c6c458c5039dd3004c38b73eMark Lobodzinski // Use SPIRV-Tools validator to try and catch any issues with the module itself 9093e3443707b0f51ba7c6c458c5039dd3004c38b73eMark Lobodzinski spv_context ctx = spvContextCreate(SPV_ENV_VULKAN_1_0); 9094e3443707b0f51ba7c6c458c5039dd3004c38b73eMark Lobodzinski spv_const_binary_t binary{pCreateInfo->pCode, pCreateInfo->codeSize / sizeof(uint32_t)}; 9095e3443707b0f51ba7c6c458c5039dd3004c38b73eMark Lobodzinski spv_diagnostic diag = nullptr; 9096b1f65702539fd041337fccd493dc6d38dd2a603eChris Forbes 9097c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski spv_valid = spvValidate(ctx, &binary, &diag); 9098c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski if (spv_valid != SPV_SUCCESS) { 90995581a92674a04d2ef49fde417e657f64e3aeed69Mark Lobodzinski if (!dev_data->device_extensions.nv_glsl_shader_enabled || (pCreateInfo->pCode[0] == spv::MagicNumber)) { 9100c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski skip_call |= log_msg(dev_data->report_data, 9101c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski spv_valid == SPV_WARNING ? VK_DEBUG_REPORT_WARNING_BIT_EXT : VK_DEBUG_REPORT_ERROR_BIT_EXT, 9102c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski VkDebugReportObjectTypeEXT(0), 0, __LINE__, SHADER_CHECKER_INCONSISTENT_SPIRV, "SC", 9103c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski "SPIR-V module not valid: %s", diag && diag->error ? diag->error : "(no error text)"); 9104c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski } 9105e3443707b0f51ba7c6c458c5039dd3004c38b73eMark Lobodzinski } 91065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9107e3443707b0f51ba7c6c458c5039dd3004c38b73eMark Lobodzinski spvDiagnosticDestroy(diag); 9108e3443707b0f51ba7c6c458c5039dd3004c38b73eMark Lobodzinski spvContextDestroy(ctx); 9109b1f65702539fd041337fccd493dc6d38dd2a603eChris Forbes 9110e3443707b0f51ba7c6c458c5039dd3004c38b73eMark Lobodzinski if (skip_call) return VK_ERROR_VALIDATION_FAILED_EXT; 9111e3443707b0f51ba7c6c458c5039dd3004c38b73eMark Lobodzinski } 91125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 91134a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult res = dev_data->dispatch_table.CreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule); 91145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9115e3443707b0f51ba7c6c458c5039dd3004c38b73eMark Lobodzinski if (res == VK_SUCCESS && !GetDisables(dev_data)->shader_validation) { 9116b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 9117c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski const auto new_shader_module = (SPV_SUCCESS == spv_valid ? new shader_module(pCreateInfo) : new shader_module()); 9118c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski dev_data->shaderModuleMap[*pShaderModule] = unique_ptr<shader_module>(new_shader_module); 91195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 91205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return res; 91215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 91225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 91234f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinskistatic bool ValidateAttachmentIndex(layer_data *dev_data, uint32_t attachment, uint32_t attachment_count, const char *type) { 91244f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski bool skip_call = false; 91254f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski if (attachment >= attachment_count && attachment != VK_ATTACHMENT_UNUSED) { 91264f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 9127e52ca7be57745459d6aa4903a3880fc8eaa9d3dcChris Forbes VALIDATION_ERROR_00325, "DS", 9128bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "CreateRenderPass: %s attachment %d must be less than the total number of attachments %d. %s", type, 9129bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski attachment, attachment_count, validation_error_map[VALIDATION_ERROR_00325]); 91304f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 91314f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski return skip_call; 91324f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski} 91334f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski 9134bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic bool IsPowerOfTwo(unsigned x) { return x && !(x & (x - 1)); } 9135805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes 91364f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinskistatic bool ValidateRenderpassAttachmentUsage(layer_data *dev_data, const VkRenderPassCreateInfo *pCreateInfo) { 91374f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski bool skip_call = false; 91384f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) { 91394f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i]; 91404f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski if (subpass.pipelineBindPoint != VK_PIPELINE_BIND_POINT_GRAPHICS) { 91419bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 91429bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt VALIDATION_ERROR_00347, "DS", 91439bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "CreateRenderPass: Pipeline bind point for subpass %d must be VK_PIPELINE_BIND_POINT_GRAPHICS. %s", 91449bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt i, validation_error_map[VALIDATION_ERROR_00347]); 91454f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 91464f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski for (uint32_t j = 0; j < subpass.preserveAttachmentCount; ++j) { 91474f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski uint32_t attachment = subpass.pPreserveAttachments[j]; 91484f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski if (attachment == VK_ATTACHMENT_UNUSED) { 91494f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 91509bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt __LINE__, VALIDATION_ERROR_00356, "DS", 91519bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "CreateRenderPass: Preserve attachment (%d) must not be VK_ATTACHMENT_UNUSED. %s", j, 91529bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt validation_error_map[VALIDATION_ERROR_00356]); 91534f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } else { 91544f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski skip_call |= ValidateAttachmentIndex(dev_data, attachment, pCreateInfo->attachmentCount, "Preserve"); 91554f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 91564f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 91576a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes 9158bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto subpass_performs_resolve = 9159bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski subpass.pResolveAttachments && 9160bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski std::any_of(subpass.pResolveAttachments, subpass.pResolveAttachments + subpass.colorAttachmentCount, 9161bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski [](VkAttachmentReference ref) { return ref.attachment != VK_ATTACHMENT_UNUSED; }); 91626a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes 9163805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes unsigned sample_count = 0; 9164805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes 91654f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) { 91664f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski uint32_t attachment; 91674f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski if (subpass.pResolveAttachments) { 91684f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski attachment = subpass.pResolveAttachments[j].attachment; 91694f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski skip_call |= ValidateAttachmentIndex(dev_data, attachment, pCreateInfo->attachmentCount, "Resolve"); 91706a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes 91716a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes if (!skip_call && attachment != VK_ATTACHMENT_UNUSED && 91726a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes pCreateInfo->pAttachments[attachment].samples != VK_SAMPLE_COUNT_1_BIT) { 91736a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, 91749bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt __LINE__, VALIDATION_ERROR_00352, "DS", 91756a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes "CreateRenderPass: Subpass %u requests multisample resolve into attachment %u, " 91769bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "which must have VK_SAMPLE_COUNT_1_BIT but has %s. %s", 91779bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt i, attachment, string_VkSampleCountFlagBits(pCreateInfo->pAttachments[attachment].samples), 91789bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt validation_error_map[VALIDATION_ERROR_00352]); 91796a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes } 91804f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 91814f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski attachment = subpass.pColorAttachments[j].attachment; 91824f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski skip_call |= ValidateAttachmentIndex(dev_data, attachment, pCreateInfo->attachmentCount, "Color"); 91836a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes 9184805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes if (!skip_call && attachment != VK_ATTACHMENT_UNUSED) { 9185805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes sample_count |= (unsigned)pCreateInfo->pAttachments[attachment].samples; 9186805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes 9187bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (subpass_performs_resolve && pCreateInfo->pAttachments[attachment].samples == VK_SAMPLE_COUNT_1_BIT) { 9188dc7c45f01ae5690f7c969b4760463c1a6bac52d5Chris Forbes skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, 91899bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt __LINE__, VALIDATION_ERROR_00351, "DS", 9190dc7c45f01ae5690f7c969b4760463c1a6bac52d5Chris Forbes "CreateRenderPass: Subpass %u requests multisample resolve from attachment %u " 91919bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "which has VK_SAMPLE_COUNT_1_BIT. %s", 91929bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt i, attachment, validation_error_map[VALIDATION_ERROR_00351]); 9193dc7c45f01ae5690f7c969b4760463c1a6bac52d5Chris Forbes } 91946a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes } 91954f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 9196dc7c45f01ae5690f7c969b4760463c1a6bac52d5Chris Forbes 91974f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) { 91984f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski uint32_t attachment = subpass.pDepthStencilAttachment->attachment; 91994f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski skip_call |= ValidateAttachmentIndex(dev_data, attachment, pCreateInfo->attachmentCount, "Depth stencil"); 9200805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes 9201805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes if (!skip_call && attachment != VK_ATTACHMENT_UNUSED) { 9202805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes sample_count |= (unsigned)pCreateInfo->pAttachments[attachment].samples; 9203805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes } 92044f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 9205dc7c45f01ae5690f7c969b4760463c1a6bac52d5Chris Forbes 92064f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) { 92074f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski uint32_t attachment = subpass.pInputAttachments[j].attachment; 92084f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski skip_call |= ValidateAttachmentIndex(dev_data, attachment, pCreateInfo->attachmentCount, "Input"); 92094f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 9210805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes 9211805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes if (sample_count && !IsPowerOfTwo(sample_count)) { 92129bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 9213cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VALIDATION_ERROR_00337, "DS", 9214cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "CreateRenderPass: Subpass %u attempts to render to " 9215cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "attachments with inconsistent sample counts. %s", 92169bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt i, validation_error_map[VALIDATION_ERROR_00337]); 9217805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes } 92184f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 92194f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski return skip_call; 92204f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski} 92214f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski 922289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateRenderPass(VkDevice device, const VkRenderPassCreateInfo *pCreateInfo, 92234f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass) { 9224e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool skip_call = false; 922556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 92264f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski 92274f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski std::unique_lock<std::mutex> lock(global_lock); 92284f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski // TODO: As part of wrapping up the mem_tracker/core_validation merge the following routine should be consolidated with 92294f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski // ValidateLayouts. 92304f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski skip_call |= ValidateRenderpassAttachmentUsage(dev_data, pCreateInfo); 9231208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->dependencyCount; ++i) { 9232208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis skip_call |= ValidateStageMaskGsTsEnables(dev_data, pCreateInfo->pDependencies[i].srcStageMask, "vkCreateRenderPass()", 9233208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis VALIDATION_ERROR_00368, VALIDATION_ERROR_00370); 9234208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis skip_call |= ValidateStageMaskGsTsEnables(dev_data, pCreateInfo->pDependencies[i].dstStageMask, "vkCreateRenderPass()", 9235208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis VALIDATION_ERROR_00369, VALIDATION_ERROR_00371); 9236208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis } 9237ab38df28c5ae1816c5fa33c0c7840c6950e83f0dChris Forbes if (!skip_call) { 9238ab38df28c5ae1816c5fa33c0c7840c6950e83f0dChris Forbes skip_call |= ValidateLayouts(dev_data, device, pCreateInfo); 9239ab38df28c5ae1816c5fa33c0c7840c6950e83f0dChris Forbes } 9240ff6101de02d1677fb54962e2ff57875e76898e26Chris Forbes lock.unlock(); 92414f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski 92424f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski if (skip_call) { 92434f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski return VK_ERROR_VALIDATION_FAILED_EXT; 92444f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 92454f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski 92464a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateRenderPass(device, pCreateInfo, pAllocator, pRenderPass); 9247ff6101de02d1677fb54962e2ff57875e76898e26Chris Forbes 92485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 92494f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski lock.lock(); 92504f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski 92514f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski std::vector<bool> has_self_dependency(pCreateInfo->subpassCount); 92524f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski std::vector<DAGNode> subpass_to_node(pCreateInfo->subpassCount); 92534f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski skip_call |= CreatePassDAG(dev_data, device, pCreateInfo, subpass_to_node, has_self_dependency); 92544f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski 9255127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis auto render_pass = unique_ptr<RENDER_PASS_STATE>(new RENDER_PASS_STATE(pCreateInfo)); 925698cddf7090b5d5dcc382045867753ef703d1c3d3Chris Forbes render_pass->renderPass = *pRenderPass; 9257cf2686cdbb12af8a29ca598c126b5e37215f0ef7Chris Forbes render_pass->hasSelfDependency = has_self_dependency; 9258cf2686cdbb12af8a29ca598c126b5e37215f0ef7Chris Forbes render_pass->subpassToNode = subpass_to_node; 9259db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes 926087e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis // TODO: Maybe fill list and then copy instead of locking 9261cf2686cdbb12af8a29ca598c126b5e37215f0ef7Chris Forbes std::unordered_map<uint32_t, bool> &attachment_first_read = render_pass->attachment_first_read; 92626600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski std::unordered_map<uint32_t, VkImageLayout> &attachment_first_layout = render_pass->attachment_first_layout; 926387e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) { 926487e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i]; 926587e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) { 92664f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski uint32_t attachment = subpass.pColorAttachments[j].attachment; 92674f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski if (!attachment_first_read.count(attachment)) { 92684f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski attachment_first_read.insert(std::make_pair(attachment, false)); 92694f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski attachment_first_layout.insert(std::make_pair(attachment, subpass.pColorAttachments[j].layout)); 92700d615f0a5724edac98475366cf3e486dccc1f2d6Michael Lentine } 927187e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis } 927287e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) { 927387e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis uint32_t attachment = subpass.pDepthStencilAttachment->attachment; 92744f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski if (!attachment_first_read.count(attachment)) { 92754f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski attachment_first_read.insert(std::make_pair(attachment, false)); 92764f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski attachment_first_layout.insert(std::make_pair(attachment, subpass.pDepthStencilAttachment->layout)); 927724991fb692f7e2d457da50d50c40f2705591300cMichael Lentine } 927887e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis } 9279a5ce96d7c88653668a2b33a6b72bd3cb16d73f48Michael Lentine for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) { 9280a5ce96d7c88653668a2b33a6b72bd3cb16d73f48Michael Lentine uint32_t attachment = subpass.pInputAttachments[j].attachment; 92814f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski if (!attachment_first_read.count(attachment)) { 92824f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski attachment_first_read.insert(std::make_pair(attachment, true)); 92834f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski attachment_first_layout.insert(std::make_pair(attachment, subpass.pInputAttachments[j].layout)); 928424991fb692f7e2d457da50d50c40f2705591300cMichael Lentine } 9285a5ce96d7c88653668a2b33a6b72bd3cb16d73f48Michael Lentine } 928687e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis } 9287db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes 9288fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes dev_data->renderPassMap[*pRenderPass] = std::move(render_pass); 92895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 92905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 92915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 92924f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski 92939bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardtstatic bool validatePrimaryCommandBuffer(const layer_data *dev_data, const GLOBAL_CB_NODE *pCB, const std::string &cmd_name, 92949bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt UNIQUE_VALIDATION_ERROR_CODE error_code) { 9295e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool skip_call = false; 92965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB->createInfo.level != VK_COMMAND_BUFFER_LEVEL_PRIMARY) { 92978860b85a52096f9f9b28616bc37feed505497a54Chris Forbes skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 92989bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt error_code, "DS", "Cannot execute command %s on a secondary command buffer. %s", cmd_name.c_str(), 92999bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt validation_error_map[error_code]); 93005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 93015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return skip_call; 93025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 93035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 93048860b85a52096f9f9b28616bc37feed505497a54Chris Forbesstatic bool VerifyRenderAreaBounds(const layer_data *dev_data, const VkRenderPassBeginInfo *pRenderPassBegin) { 9305885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine bool skip_call = false; 9306c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis const safe_VkFramebufferCreateInfo *pFramebufferInfo = 93079a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis &GetFramebufferState(dev_data, pRenderPassBegin->framebuffer)->createInfo; 9308885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine if (pRenderPassBegin->renderArea.offset.x < 0 || 9309885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine (pRenderPassBegin->renderArea.offset.x + pRenderPassBegin->renderArea.extent.width) > pFramebufferInfo->width || 9310885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine pRenderPassBegin->renderArea.offset.y < 0 || 9311885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine (pRenderPassBegin->renderArea.offset.y + pRenderPassBegin->renderArea.extent.height) > pFramebufferInfo->height) { 9312885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine skip_call |= static_cast<bool>(log_msg( 93138860b85a52096f9f9b28616bc37feed505497a54Chris Forbes dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 9314885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine DRAWSTATE_INVALID_RENDER_AREA, "CORE", 9315885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine "Cannot execute a render pass with renderArea not within the bound of the " 9316885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine "framebuffer. RenderArea: x %d, y %d, width %d, height %d. Framebuffer: width %d, " 9317885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine "height %d.", 9318885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine pRenderPassBegin->renderArea.offset.x, pRenderPassBegin->renderArea.offset.y, pRenderPassBegin->renderArea.extent.width, 9319885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine pRenderPassBegin->renderArea.extent.height, pFramebufferInfo->width, pFramebufferInfo->height)); 9320885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine } 9321885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine return skip_call; 9322885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine} 9323885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine 93241a65650f856376768d7b03ea2d080aaff87cacfdMark 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 93251a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski// [load|store]Op flag must be checked 93261a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski// TODO: The memory valid flag in DEVICE_MEM_INFO should probably be split to track the validity of stencil memory separately. 9327cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskitemplate <typename T> 9328cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskistatic bool FormatSpecificLoadAndStoreOpSettings(VkFormat format, T color_depth_op, T stencil_op, T op) { 9329a49b8a211ce07e7fa2225d23f8cb11f1055b418aMark Lobodzinski if (color_depth_op != op && stencil_op != op) { 9330a49b8a211ce07e7fa2225d23f8cb11f1055b418aMark Lobodzinski return false; 9331a49b8a211ce07e7fa2225d23f8cb11f1055b418aMark Lobodzinski } 93321a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski bool check_color_depth_load_op = !vk_format_is_stencil_only(format); 93331a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski bool check_stencil_load_op = vk_format_is_depth_and_stencil(format) || !check_color_depth_load_op; 9334a49b8a211ce07e7fa2225d23f8cb11f1055b418aMark Lobodzinski 9335a49b8a211ce07e7fa2225d23f8cb11f1055b418aMark Lobodzinski return (((check_color_depth_load_op == true) && (color_depth_op == op)) || 9336a49b8a211ce07e7fa2225d23f8cb11f1055b418aMark Lobodzinski ((check_stencil_load_op == true) && (stencil_op == op))); 93371a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski} 93381a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski 9339bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBeginRenderPass(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *pRenderPassBegin, 9340bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkSubpassContents contents) { 934183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 934256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 9343b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 93449a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *cb_node = GetCBNode(dev_data, commandBuffer); 93459a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto render_pass_state = pRenderPassBegin ? GetRenderPassState(dev_data, pRenderPassBegin->renderPass) : nullptr; 93469a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto framebuffer = pRenderPassBegin ? GetFramebufferState(dev_data, pRenderPassBegin->framebuffer) : nullptr; 9347f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis if (cb_node) { 9348308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski if (render_pass_state) { 9349cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski uint32_t clear_op_size = 0; // Make sure pClearValues is at least as large as last LOAD_OP_CLEAR 9350f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->activeFramebuffer = pRenderPassBegin->framebuffer; 9351308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski for (uint32_t i = 0; i < render_pass_state->createInfo.attachmentCount; ++i) { 9352f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes MT_FB_ATTACHMENT_INFO &fb_info = framebuffer->attachments[i]; 9353308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski auto pAttachment = &render_pass_state->createInfo.pAttachments[i]; 9354bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (FormatSpecificLoadAndStoreOpSettings(pAttachment->format, pAttachment->loadOp, pAttachment->stencilLoadOp, 93551a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski VK_ATTACHMENT_LOAD_OP_CLEAR)) { 935692bc0680357019834b7529148ab6d73353ce02c7Mark Lobodzinski clear_op_size = static_cast<uint32_t>(i) + 1; 935716387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes std::function<bool()> function = [=]() { 93589a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis SetImageMemoryValid(dev_data, GetImageState(dev_data, fb_info.image), true); 935916387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes return false; 936016387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes }; 9361f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->validate_functions.push_back(function); 9362db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes } else if (FormatSpecificLoadAndStoreOpSettings(pAttachment->format, pAttachment->loadOp, 9363bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pAttachment->stencilLoadOp, VK_ATTACHMENT_LOAD_OP_DONT_CARE)) { 936416387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes std::function<bool()> function = [=]() { 93659a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis SetImageMemoryValid(dev_data, GetImageState(dev_data, fb_info.image), false); 936616387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes return false; 936716387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes }; 9368f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->validate_functions.push_back(function); 9369db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes } else if (FormatSpecificLoadAndStoreOpSettings(pAttachment->format, pAttachment->loadOp, 9370bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pAttachment->stencilLoadOp, VK_ATTACHMENT_LOAD_OP_LOAD)) { 937116387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes std::function<bool()> function = [=]() { 93729a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis return ValidateImageMemoryIsValid(dev_data, GetImageState(dev_data, fb_info.image), 9373f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis "vkCmdBeginRenderPass()"); 937416387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes }; 9375f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->validate_functions.push_back(function); 937616387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes } 9377308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski if (render_pass_state->attachment_first_read[i]) { 937816387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes std::function<bool()> function = [=]() { 93799a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis return ValidateImageMemoryIsValid(dev_data, GetImageState(dev_data, fb_info.image), 9380f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis "vkCmdBeginRenderPass()"); 938116387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes }; 9382f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->validate_functions.push_back(function); 93835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 93845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 93856de3c6ffa0819ee37cd5cecee918b062145e2ff1Tobin Ehlis if (clear_op_size > pRenderPassBegin->clearValueCount) { 9386369cf6deef1fca74f9eb1f8ef6e96deba715b133Slawomir Cygan skip_call |= log_msg( 9387369cf6deef1fca74f9eb1f8ef6e96deba715b133Slawomir Cygan dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT, 9388308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski reinterpret_cast<uint64_t &>(render_pass_state->renderPass), __LINE__, VALIDATION_ERROR_00442, "DS", 9389bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "In vkCmdBeginRenderPass() the VkRenderPassBeginInfo struct has a clearValueCount of %u but there must " 9390bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "be at least %u entries in pClearValues array to account for the highest index attachment in renderPass " 9391cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "0x%" PRIx64 9392cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " that uses VK_ATTACHMENT_LOAD_OP_CLEAR is %u. Note that the pClearValues array " 9393bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "is indexed by attachment number so even if some pClearValues entries between 0 and %u correspond to " 9394bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "attachments that aren't cleared they will be ignored. %s", 9395308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski pRenderPassBegin->clearValueCount, clear_op_size, reinterpret_cast<uint64_t &>(render_pass_state->renderPass), 93965504d0369cbc97ad7c221eddbad439bfb83e3fb6Mark Lobodzinski clear_op_size, clear_op_size - 1, validation_error_map[VALIDATION_ERROR_00442]); 9397369cf6deef1fca74f9eb1f8ef6e96deba715b133Slawomir Cygan } 9398369cf6deef1fca74f9eb1f8ef6e96deba715b133Slawomir Cygan if (clear_op_size < pRenderPassBegin->clearValueCount) { 9399369cf6deef1fca74f9eb1f8ef6e96deba715b133Slawomir Cygan skip_call |= log_msg( 9400369cf6deef1fca74f9eb1f8ef6e96deba715b133Slawomir Cygan dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT, 9401308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski reinterpret_cast<uint64_t &>(render_pass_state->renderPass), __LINE__, 9402308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski DRAWSTATE_RENDERPASS_TOO_MANY_CLEAR_VALUES, "DS", 9403369cf6deef1fca74f9eb1f8ef6e96deba715b133Slawomir Cygan "In vkCmdBeginRenderPass() the VkRenderPassBeginInfo struct has a clearValueCount of %u but only first %u " 94047bab3d8f0599701f6e26a2d76314588486ae99c9Mark Lobodzinski "entries in pClearValues array are used. The highest index of any attachment in renderPass 0x%" PRIx64 9405369cf6deef1fca74f9eb1f8ef6e96deba715b133Slawomir Cygan " that uses VK_ATTACHMENT_LOAD_OP_CLEAR is %u - other pClearValues are ignored.", 9406308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski pRenderPassBegin->clearValueCount, clear_op_size, reinterpret_cast<uint64_t &>(render_pass_state->renderPass), 94077bab3d8f0599701f6e26a2d76314588486ae99c9Mark Lobodzinski clear_op_size - 1); 94083d71bca42a843966040d6ada9c029e0ec9f35ca6Tobin Ehlis } 940983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= VerifyRenderAreaBounds(dev_data, pRenderPassBegin); 941055867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski skip_call |= VerifyFramebufferAndRenderPassLayouts(dev_data, cb_node, pRenderPassBegin, 94119a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GetFramebufferState(dev_data, pRenderPassBegin->framebuffer)); 9412ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen skip_call |= insideRenderPass(dev_data, cb_node, "vkCmdBeginRenderPass()", VALIDATION_ERROR_00440); 9413308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski skip_call |= ValidateDependencies(dev_data, framebuffer, render_pass_state); 94149bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt skip_call |= validatePrimaryCommandBuffer(dev_data, cb_node, "vkCmdBeginRenderPass", VALIDATION_ERROR_00441); 941529f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, cb_node, CMD_BEGINRENDERPASS, "vkCmdBeginRenderPass()"); 94161ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(cb_node, CMD_BEGINRENDERPASS); 9417308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski cb_node->activeRenderPass = render_pass_state; 94185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // This is a shallow copy as that is all that is needed for now 9419f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->activeRenderPassBeginInfo = *pRenderPassBegin; 9420f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->activeSubpass = 0; 9421f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->activeSubpassContents = contents; 9422f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->framebuffers.insert(pRenderPassBegin->framebuffer); 9423883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis // Connect this framebuffer and its children to this cmdBuffer 9424883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis AddFramebufferBinding(dev_data, cb_node, framebuffer); 9425ea0f86230ff5c52f805ac831a1ed5a92bd123368Chris Forbes // transition attachments to the correct layouts for the first subpass 942655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski TransitionSubpassLayouts(dev_data, cb_node, &cb_node->activeRenderPassBeginInfo, cb_node->activeSubpass, framebuffer); 94275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 94285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9429b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 943083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis if (!skip_call) { 94314a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdBeginRenderPass(commandBuffer, pRenderPassBegin, contents); 94325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 94335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 94345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 943589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents) { 943683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 943756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 9438b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 94399a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 94405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 94419bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt skip_call |= validatePrimaryCommandBuffer(dev_data, pCB, "vkCmdNextSubpass", VALIDATION_ERROR_00459); 944229f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_NEXTSUBPASS, "vkCmdNextSubpass()"); 94431ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_NEXTSUBPASS); 9444ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen skip_call |= outsideRenderPass(dev_data, pCB, "vkCmdNextSubpass()", VALIDATION_ERROR_00458); 944580281691386b37385846f21b38e8c9d4b12cc74eChris Forbes 9446fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes auto subpassCount = pCB->activeRenderPass->createInfo.subpassCount; 944780281691386b37385846f21b38e8c9d4b12cc74eChris Forbes if (pCB->activeSubpass == subpassCount - 1) { 94489bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt skip_call |= log_msg( 94499bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 94509bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt reinterpret_cast<uint64_t>(commandBuffer), __LINE__, VALIDATION_ERROR_00453, "DS", 94519bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "vkCmdNextSubpass(): Attempted to advance beyond final subpass. %s", validation_error_map[VALIDATION_ERROR_00453]); 945280281691386b37385846f21b38e8c9d4b12cc74eChris Forbes } 94535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9454b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 945596ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes 9456cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip_call) return; 945796ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes 94584a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdNextSubpass(commandBuffer, contents); 945996ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes 946096ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes if (pCB) { 9461bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski lock.lock(); 9462bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pCB->activeSubpass++; 9463bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pCB->activeSubpassContents = contents; 946455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski TransitionSubpassLayouts(dev_data, pCB, &pCB->activeRenderPassBeginInfo, pCB->activeSubpass, 94659a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GetFramebufferState(dev_data, pCB->activeRenderPassBeginInfo.framebuffer)); 946696ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes } 94675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 94685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 946989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdEndRenderPass(VkCommandBuffer commandBuffer) { 947083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 947156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 9472b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 94739a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pCB = GetCBNode(dev_data, commandBuffer); 947455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski FRAMEBUFFER_STATE *framebuffer = NULL; 947558c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes if (pCB) { 9476127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis RENDER_PASS_STATE *rp_state = pCB->activeRenderPass; 94779a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis framebuffer = GetFramebufferState(dev_data, pCB->activeFramebuffer); 9478127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis if (rp_state) { 9479127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis if (pCB->activeSubpass != rp_state->createInfo.subpassCount - 1) { 94809bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt skip_call |= log_msg( 94819bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 94829bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt reinterpret_cast<uint64_t>(commandBuffer), __LINE__, VALIDATION_ERROR_00460, "DS", 94839bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "vkCmdEndRenderPass(): Called before reaching final subpass. %s", validation_error_map[VALIDATION_ERROR_00460]); 948402a3382f28fc7c6ec6018165be88aa6fc4f05c9eChris Forbes } 948502a3382f28fc7c6ec6018165be88aa6fc4f05c9eChris Forbes 9486127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis for (size_t i = 0; i < rp_state->createInfo.attachmentCount; ++i) { 9487e3ad4b1284408353cc56a04951c1df1f35a636ceChris Forbes MT_FB_ATTACHMENT_INFO &fb_info = framebuffer->attachments[i]; 9488127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis auto pAttachment = &rp_state->createInfo.pAttachments[i]; 9489bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (FormatSpecificLoadAndStoreOpSettings(pAttachment->format, pAttachment->storeOp, pAttachment->stencilStoreOp, 9490bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VK_ATTACHMENT_STORE_OP_STORE)) { 949158c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes std::function<bool()> function = [=]() { 94929a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis SetImageMemoryValid(dev_data, GetImageState(dev_data, fb_info.image), true); 949358c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes return false; 949458c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes }; 949558c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes pCB->validate_functions.push_back(function); 9496db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes } else if (FormatSpecificLoadAndStoreOpSettings(pAttachment->format, pAttachment->storeOp, 9497bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pAttachment->stencilStoreOp, VK_ATTACHMENT_STORE_OP_DONT_CARE)) { 949858c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes std::function<bool()> function = [=]() { 94999a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis SetImageMemoryValid(dev_data, GetImageState(dev_data, fb_info.image), false); 950058c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes return false; 950158c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes }; 950258c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes pCB->validate_functions.push_back(function); 95035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 95045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 95055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9506ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen skip_call |= outsideRenderPass(dev_data, pCB, "vkCmdEndRenderpass()", VALIDATION_ERROR_00464); 95079bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt skip_call |= validatePrimaryCommandBuffer(dev_data, pCB, "vkCmdEndRenderPass", VALIDATION_ERROR_00465); 950829f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_ENDRENDERPASS, "vkCmdEndRenderPass()"); 95091ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_ENDRENDERPASS); 95100e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes } 95110e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes lock.unlock(); 95120e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes 9513cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip_call) return; 95140e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes 95154a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdEndRenderPass(commandBuffer); 95160e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes 95170e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes if (pCB) { 95180e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes lock.lock(); 951955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski TransitionFinalSubpassLayouts(dev_data, pCB, &pCB->activeRenderPassBeginInfo, framebuffer); 952058c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes pCB->activeRenderPass = nullptr; 952158c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes pCB->activeSubpass = 0; 952258c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes pCB->activeFramebuffer = VK_NULL_HANDLE; 95235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 95245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 95255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9526a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlisstatic bool logInvalidAttachmentMessage(layer_data *dev_data, VkCommandBuffer secondaryBuffer, uint32_t primaryAttach, 9527a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis uint32_t secondaryAttach, const char *msg) { 95285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 9529cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VALIDATION_ERROR_02059, "DS", "vkCmdExecuteCommands() called w/ invalid Secondary Cmd Buffer 0x%" PRIx64 9530cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " which has a render pass " 9531cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "that is not compatible with the Primary Cmd Buffer current render pass. " 9532cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Attachment %u is not compatible with %u: %s. %s", 95339bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt reinterpret_cast<uint64_t &>(secondaryBuffer), primaryAttach, secondaryAttach, msg, 95349bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt validation_error_map[VALIDATION_ERROR_02059]); 95355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 95365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9537a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlisstatic bool validateAttachmentCompatibility(layer_data *dev_data, VkCommandBuffer primaryBuffer, 9538a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis VkRenderPassCreateInfo const *primaryPassCI, uint32_t primaryAttach, 9539a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis VkCommandBuffer secondaryBuffer, VkRenderPassCreateInfo const *secondaryPassCI, 9540e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves uint32_t secondaryAttach, bool is_multi) { 95415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool skip_call = false; 9542a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis if (primaryPassCI->attachmentCount <= primaryAttach) { 95435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis primaryAttach = VK_ATTACHMENT_UNUSED; 95445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9545a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis if (secondaryPassCI->attachmentCount <= secondaryAttach) { 95465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis secondaryAttach = VK_ATTACHMENT_UNUSED; 95475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 95485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (primaryAttach == VK_ATTACHMENT_UNUSED && secondaryAttach == VK_ATTACHMENT_UNUSED) { 95495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return skip_call; 95505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 95515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (primaryAttach == VK_ATTACHMENT_UNUSED) { 9552a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis skip_call |= logInvalidAttachmentMessage(dev_data, secondaryBuffer, primaryAttach, secondaryAttach, 9553a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis "The first is unused while the second is not."); 95545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return skip_call; 95555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 95565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (secondaryAttach == VK_ATTACHMENT_UNUSED) { 9557a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis skip_call |= logInvalidAttachmentMessage(dev_data, secondaryBuffer, primaryAttach, secondaryAttach, 9558a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis "The second is unused while the first is not."); 95595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return skip_call; 95605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9561a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis if (primaryPassCI->pAttachments[primaryAttach].format != secondaryPassCI->pAttachments[secondaryAttach].format) { 9562a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis skip_call |= 9563a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis logInvalidAttachmentMessage(dev_data, secondaryBuffer, primaryAttach, secondaryAttach, "They have different formats."); 95645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9565a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis if (primaryPassCI->pAttachments[primaryAttach].samples != secondaryPassCI->pAttachments[secondaryAttach].samples) { 9566a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis skip_call |= 9567a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis logInvalidAttachmentMessage(dev_data, secondaryBuffer, primaryAttach, secondaryAttach, "They have different samples."); 95685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9569a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis if (is_multi && primaryPassCI->pAttachments[primaryAttach].flags != secondaryPassCI->pAttachments[secondaryAttach].flags) { 9570a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis skip_call |= 9571a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis logInvalidAttachmentMessage(dev_data, secondaryBuffer, primaryAttach, secondaryAttach, "They have different flags."); 95725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 95735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return skip_call; 95745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 95755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9576a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlisstatic bool validateSubpassCompatibility(layer_data *dev_data, VkCommandBuffer primaryBuffer, 9577a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis VkRenderPassCreateInfo const *primaryPassCI, VkCommandBuffer secondaryBuffer, 9578a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis VkRenderPassCreateInfo const *secondaryPassCI, const int subpass, bool is_multi) { 95795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool skip_call = false; 9580a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis const VkSubpassDescription &primary_desc = primaryPassCI->pSubpasses[subpass]; 9581a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis const VkSubpassDescription &secondary_desc = secondaryPassCI->pSubpasses[subpass]; 95825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t maxInputAttachmentCount = std::max(primary_desc.inputAttachmentCount, secondary_desc.inputAttachmentCount); 95835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < maxInputAttachmentCount; ++i) { 95845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t primary_input_attach = VK_ATTACHMENT_UNUSED, secondary_input_attach = VK_ATTACHMENT_UNUSED; 95855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (i < primary_desc.inputAttachmentCount) { 95865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis primary_input_attach = primary_desc.pInputAttachments[i].attachment; 95875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 95885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (i < secondary_desc.inputAttachmentCount) { 95895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis secondary_input_attach = secondary_desc.pInputAttachments[i].attachment; 95905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9591a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis skip_call |= validateAttachmentCompatibility(dev_data, primaryBuffer, primaryPassCI, primary_input_attach, secondaryBuffer, 9592a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis secondaryPassCI, secondary_input_attach, is_multi); 95935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 95945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t maxColorAttachmentCount = std::max(primary_desc.colorAttachmentCount, secondary_desc.colorAttachmentCount); 95955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < maxColorAttachmentCount; ++i) { 95965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t primary_color_attach = VK_ATTACHMENT_UNUSED, secondary_color_attach = VK_ATTACHMENT_UNUSED; 95975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (i < primary_desc.colorAttachmentCount) { 95985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis primary_color_attach = primary_desc.pColorAttachments[i].attachment; 95995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 96005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (i < secondary_desc.colorAttachmentCount) { 96015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis secondary_color_attach = secondary_desc.pColorAttachments[i].attachment; 96025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9603a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis skip_call |= validateAttachmentCompatibility(dev_data, primaryBuffer, primaryPassCI, primary_color_attach, secondaryBuffer, 9604a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis secondaryPassCI, secondary_color_attach, is_multi); 96055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t primary_resolve_attach = VK_ATTACHMENT_UNUSED, secondary_resolve_attach = VK_ATTACHMENT_UNUSED; 96065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (i < primary_desc.colorAttachmentCount && primary_desc.pResolveAttachments) { 96075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis primary_resolve_attach = primary_desc.pResolveAttachments[i].attachment; 96085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 96095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (i < secondary_desc.colorAttachmentCount && secondary_desc.pResolveAttachments) { 96105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis secondary_resolve_attach = secondary_desc.pResolveAttachments[i].attachment; 96115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9612a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis skip_call |= validateAttachmentCompatibility(dev_data, primaryBuffer, primaryPassCI, primary_resolve_attach, 9613a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis secondaryBuffer, secondaryPassCI, secondary_resolve_attach, is_multi); 96145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 96155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t primary_depthstencil_attach = VK_ATTACHMENT_UNUSED, secondary_depthstencil_attach = VK_ATTACHMENT_UNUSED; 96165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (primary_desc.pDepthStencilAttachment) { 96175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis primary_depthstencil_attach = primary_desc.pDepthStencilAttachment[0].attachment; 96185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 96195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (secondary_desc.pDepthStencilAttachment) { 96205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis secondary_depthstencil_attach = secondary_desc.pDepthStencilAttachment[0].attachment; 96215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9622a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis skip_call |= validateAttachmentCompatibility(dev_data, primaryBuffer, primaryPassCI, primary_depthstencil_attach, 9623a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis secondaryBuffer, secondaryPassCI, secondary_depthstencil_attach, is_multi); 96245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return skip_call; 96255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 96265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9627a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis// Verify that given renderPass CreateInfo for primary and secondary command buffers are compatible. 9628a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis// This function deals directly with the CreateInfo, there are overloaded versions below that can take the renderPass handle and 9629a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis// will then feed into this function 9630a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlisstatic bool validateRenderPassCompatibility(layer_data *dev_data, VkCommandBuffer primaryBuffer, 9631a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis VkRenderPassCreateInfo const *primaryPassCI, VkCommandBuffer secondaryBuffer, 9632a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis VkRenderPassCreateInfo const *secondaryPassCI) { 96335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool skip_call = false; 9634a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis 9635a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis if (primaryPassCI->subpassCount != secondaryPassCI->subpassCount) { 96365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 96375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS", 9638a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis "vkCmdExecuteCommands() called w/ invalid secondary Cmd Buffer 0x%" PRIx64 9639a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis " that has a subpassCount of %u that is incompatible with the primary Cmd Buffer 0x%" PRIx64 9640a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis " that has a subpassCount of %u.", 9641a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis reinterpret_cast<uint64_t &>(secondaryBuffer), secondaryPassCI->subpassCount, 9642a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis reinterpret_cast<uint64_t &>(primaryBuffer), primaryPassCI->subpassCount); 9643a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis } else { 9644a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis for (uint32_t i = 0; i < primaryPassCI->subpassCount; ++i) { 9645a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis skip_call |= validateSubpassCompatibility(dev_data, primaryBuffer, primaryPassCI, secondaryBuffer, secondaryPassCI, i, 9646a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis primaryPassCI->subpassCount > 1); 9647a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis } 96485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 96495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return skip_call; 96505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 96515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9652e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool validateFramebuffer(layer_data *dev_data, VkCommandBuffer primaryBuffer, const GLOBAL_CB_NODE *pCB, 9653e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves VkCommandBuffer secondaryBuffer, const GLOBAL_CB_NODE *pSubCB) { 96545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool skip_call = false; 96555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!pSubCB->beginInfo.pInheritanceInfo) { 96565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return skip_call; 96575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9658c5b97dda856ff837638b3ebb7e231d5507c495a3Chris Forbes VkFramebuffer primary_fb = pCB->activeFramebuffer; 96595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkFramebuffer secondary_fb = pSubCB->beginInfo.pInheritanceInfo->framebuffer; 96605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (secondary_fb != VK_NULL_HANDLE) { 96615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (primary_fb != secondary_fb) { 96629bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt skip_call |= log_msg( 96639bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 96649bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt VALIDATION_ERROR_02060, "DS", 96659bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "vkCmdExecuteCommands() called w/ invalid secondary command buffer 0x%" PRIx64 " which has a framebuffer 0x%" PRIx64 96669bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt " that is not the same as the primary command buffer's current active framebuffer 0x%" PRIx64 ". %s", 96679bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt reinterpret_cast<uint64_t &>(secondaryBuffer), reinterpret_cast<uint64_t &>(secondary_fb), 96689bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt reinterpret_cast<uint64_t &>(primary_fb), validation_error_map[VALIDATION_ERROR_02060]); 96695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 96709a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto fb = GetFramebufferState(dev_data, secondary_fb); 9671e3ad4b1284408353cc56a04951c1df1f35a636ceChris Forbes if (!fb) { 9672bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 9673bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS", 9674bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "vkCmdExecuteCommands() called w/ invalid Cmd Buffer 0x%p " 9675bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "which has invalid framebuffer 0x%" PRIx64 ".", 9676bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski (void *)secondaryBuffer, (uint64_t)(secondary_fb)); 96775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return skip_call; 96785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 96799a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_renderpass = GetRenderPassState(dev_data, pSubCB->beginInfo.pInheritanceInfo->renderPass); 9680a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis if (cb_renderpass->renderPass != fb->createInfo.renderPass) { 9681a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis skip_call |= validateRenderPassCompatibility(dev_data, secondaryBuffer, fb->renderPassCreateInfo.ptr(), secondaryBuffer, 9682fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes cb_renderpass->createInfo.ptr()); 9683a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis } 96845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 96855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return skip_call; 96865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 96875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9688e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool validateSecondaryCommandBufferState(layer_data *dev_data, GLOBAL_CB_NODE *pCB, GLOBAL_CB_NODE *pSubCB) { 968983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 96905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unordered_set<int> activeTypes; 96915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto queryObject : pCB->activeQueries) { 96925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto queryPoolData = dev_data->queryPoolMap.find(queryObject.pool); 96935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (queryPoolData != dev_data->queryPoolMap.end()) { 96945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (queryPoolData->second.createInfo.queryType == VK_QUERY_TYPE_PIPELINE_STATISTICS && 96955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pSubCB->beginInfo.pInheritanceInfo) { 96965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkQueryPipelineStatisticFlags cmdBufStatistics = pSubCB->beginInfo.pInheritanceInfo->pipelineStatistics; 96975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if ((cmdBufStatistics & queryPoolData->second.createInfo.pipelineStatistics) != cmdBufStatistics) { 9698cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 9699cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, VALIDATION_ERROR_02065, "DS", 9700cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkCmdExecuteCommands() called w/ invalid Cmd Buffer 0x%p " 9701cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "which has invalid active query pool 0x%" PRIx64 9702cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ". Pipeline statistics is being queried so the command " 9703cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "buffer must have all bits set on the queryPool. %s", 9704cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pCB->commandBuffer, reinterpret_cast<const uint64_t &>(queryPoolData->first), 9705cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski validation_error_map[VALIDATION_ERROR_02065]); 97065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 97075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 97085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis activeTypes.insert(queryPoolData->second.createInfo.queryType); 97095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 97105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 97115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto queryObject : pSubCB->startedQueries) { 97125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto queryPoolData = dev_data->queryPoolMap.find(queryObject.pool); 97135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (queryPoolData != dev_data->queryPoolMap.end() && activeTypes.count(queryPoolData->second.createInfo.queryType)) { 9714cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 9715cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS", 9716cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkCmdExecuteCommands() called w/ invalid Cmd Buffer 0x%p " 9717cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "which has invalid active query pool 0x%" PRIx64 9718cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "of type %d but a query of that type has been started on " 9719cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "secondary Cmd Buffer 0x%p.", 9720cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pCB->commandBuffer, reinterpret_cast<const uint64_t &>(queryPoolData->first), 9721cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski queryPoolData->second.createInfo.queryType, pSubCB->commandBuffer); 97225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 97235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 97247bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski 97259a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto primary_pool = GetCommandPoolNode(dev_data, pCB->createInfo.commandPool); 97269a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto secondary_pool = GetCommandPoolNode(dev_data, pSubCB->createInfo.commandPool); 97277bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski if (primary_pool && secondary_pool && (primary_pool->queueFamilyIndex != secondary_pool->queueFamilyIndex)) { 9728226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis skip_call |= 9729226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 9730226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis reinterpret_cast<uint64_t>(pSubCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_QUEUE_FAMILY, "DS", 9731226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "vkCmdExecuteCommands(): Primary command buffer 0x%p" 9732226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis " created in queue family %d has secondary command buffer 0x%p created in queue family %d.", 9733226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis pCB->commandBuffer, primary_pool->queueFamilyIndex, pSubCB->commandBuffer, secondary_pool->queueFamilyIndex); 97347bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski } 97357bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski 973683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis return skip_call; 97375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 97385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9739bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t commandBuffersCount, 9740bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkCommandBuffer *pCommandBuffers) { 974183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 974256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 9743b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 97449a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 97455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 97465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis GLOBAL_CB_NODE *pSubCB = NULL; 97475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < commandBuffersCount; i++) { 97489a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis pSubCB = GetCBNode(dev_data, pCommandBuffers[i]); 97490a8b955c23012196339f3c10ffedc631ea0f7c58Tobin Ehlis assert(pSubCB); 97500a8b955c23012196339f3c10ffedc631ea0f7c58Tobin Ehlis if (VK_COMMAND_BUFFER_LEVEL_PRIMARY == pSubCB->createInfo.level) { 975183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, 97524b6738a6adb4e813d66234defee5d18b7c84340dMike Weiblen __LINE__, VALIDATION_ERROR_00153, "DS", 975383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis "vkCmdExecuteCommands() called w/ Primary Cmd Buffer 0x%p in element %u of pCommandBuffers " 97544b6738a6adb4e813d66234defee5d18b7c84340dMike Weiblen "array. All cmd buffers in pCommandBuffers array must be secondary. %s", 9755226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis pCommandBuffers[i], i, validation_error_map[VALIDATION_ERROR_00153]); 9756cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else if (pCB->activeRenderPass) { // Secondary CB w/i RenderPass must have *CONTINUE_BIT set 97579a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto secondary_rp_state = GetRenderPassState(dev_data, pSubCB->beginInfo.pInheritanceInfo->renderPass); 97585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!(pSubCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT)) { 975983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg( 97605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 97614b6738a6adb4e813d66234defee5d18b7c84340dMike Weiblen (uint64_t)pCommandBuffers[i], __LINE__, VALIDATION_ERROR_02057, "DS", 9762414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller "vkCmdExecuteCommands(): Secondary Command Buffer (0x%p) executed within render pass (0x%" PRIxLEAST64 97634b6738a6adb4e813d66234defee5d18b7c84340dMike Weiblen ") must have had vkBeginCommandBuffer() called w/ VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT set. %s", 9764226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis pCommandBuffers[i], (uint64_t)pCB->activeRenderPass->renderPass, 97654b6738a6adb4e813d66234defee5d18b7c84340dMike Weiblen validation_error_map[VALIDATION_ERROR_02057]); 97665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 97675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Make sure render pass is compatible with parent command buffer pass if has continue 9768127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis if (pCB->activeRenderPass->renderPass != secondary_rp_state->renderPass) { 9769fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes skip_call |= 9770fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes validateRenderPassCompatibility(dev_data, commandBuffer, pCB->activeRenderPass->createInfo.ptr(), 9771127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis pCommandBuffers[i], secondary_rp_state->createInfo.ptr()); 9772a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis } 97731af6125615cd6dd9735d32e2ee8684abeff28d41Tobin Ehlis // If framebuffer for secondary CB is not NULL, then it must match active FB from primaryCB 977483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= validateFramebuffer(dev_data, commandBuffer, pCB, pCommandBuffers[i], pSubCB); 97755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 97765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis string errorString = ""; 97771af6125615cd6dd9735d32e2ee8684abeff28d41Tobin Ehlis // secondaryCB must have been created w/ RP compatible w/ primaryCB active renderpass 9778127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis if ((pCB->activeRenderPass->renderPass != secondary_rp_state->renderPass) && 9779fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes !verify_renderpass_compatibility(dev_data, pCB->activeRenderPass->createInfo.ptr(), 9780127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis secondary_rp_state->createInfo.ptr(), errorString)) { 978183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg( 97825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 97835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (uint64_t)pCommandBuffers[i], __LINE__, DRAWSTATE_RENDERPASS_INCOMPATIBLE, "DS", 9784414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller "vkCmdExecuteCommands(): Secondary Command Buffer (0x%p) w/ render pass (0x%" PRIxLEAST64 9785414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller ") is incompatible w/ primary command buffer (0x%p) w/ render pass (0x%" PRIxLEAST64 ") due to: %s", 9786226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis pCommandBuffers[i], (uint64_t)pSubCB->beginInfo.pInheritanceInfo->renderPass, commandBuffer, 9787ee691f5c5fa87aac3750454d2bca2cb582e4e817Chris Forbes (uint64_t)pCB->activeRenderPass->renderPass, errorString.c_str()); 97885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 97895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 97905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODO(mlentine): Move more logic into this method 979183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= validateSecondaryCommandBufferState(dev_data, pCB, pSubCB); 979251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour skip_call |= validateCommandBufferState(dev_data, pSubCB, "vkCmdExecuteCommands()", 0); 97935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Secondary cmdBuffers are considered pending execution starting w/ 97945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // being recorded 97955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!(pSubCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT)) { 97965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (dev_data->globalInFlightCmdBuffers.find(pSubCB->commandBuffer) != dev_data->globalInFlightCmdBuffers.end()) { 9797cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 9798cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)(pCB->commandBuffer), __LINE__, 9799cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VALIDATION_ERROR_00154, "DS", 9800cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Attempt to simultaneously execute command buffer 0x%p" 9801cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " without VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT set! %s", 9802cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pCB->commandBuffer, validation_error_map[VALIDATION_ERROR_00154]); 98035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 98045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT) { 98055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Warn that non-simultaneous secondary cmd buffer renders primary non-simultaneous 980683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg( 98075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 98085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (uint64_t)(pCommandBuffers[i]), __LINE__, DRAWSTATE_INVALID_CB_SIMULTANEOUS_USE, "DS", 9809226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "vkCmdExecuteCommands(): Secondary Command Buffer (0x%p) " 9810226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "does not have VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT set and will cause primary command buffer " 9811226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "(0x%p) to be treated as if it does not have VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT " 981283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis "set, even though it does.", 9813226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis pCommandBuffers[i], pCB->commandBuffer); 98145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->beginInfo.flags &= ~VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT; 98155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 98165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9817f71dd305f197826a61f398bff725267a20ea1d90Chris Forbes if (!pCB->activeQueries.empty() && !dev_data->enabled_features.inheritedQueries) { 9818cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski skip_call |= 9819cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 9820cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski reinterpret_cast<uint64_t>(pCommandBuffers[i]), __LINE__, VALIDATION_ERROR_02062, "DS", 9821cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkCmdExecuteCommands(): Secondary Command Buffer " 9822cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "(0x%p) cannot be submitted with a query in " 9823cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "flight and inherited queries not " 9824cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "supported on this device. %s", 9825cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pCommandBuffers[i], validation_error_map[VALIDATION_ERROR_02062]); 98265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 98278567fecbf563420f5900ade277ca68908aa87259Tobin Ehlis // Propagate layout transitions to the primary cmd buffer 98288567fecbf563420f5900ade277ca68908aa87259Tobin Ehlis for (auto ilm_entry : pSubCB->imageLayoutMap) { 982955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski SetLayout(dev_data, pCB, ilm_entry.first, ilm_entry.second); 98308567fecbf563420f5900ade277ca68908aa87259Tobin Ehlis } 98315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pSubCB->primaryCommandBuffer = pCB->commandBuffer; 98325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->secondaryCommandBuffers.insert(pSubCB->commandBuffer); 98335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->globalInFlightCmdBuffers.insert(pSubCB->commandBuffer); 9834d4ee9fdb2def1e9dc70c5627c9103e264471b8ebMichael Lentine for (auto &function : pSubCB->queryUpdates) { 9835d4ee9fdb2def1e9dc70c5627c9103e264471b8ebMichael Lentine pCB->queryUpdates.push_back(function); 9836d4ee9fdb2def1e9dc70c5627c9103e264471b8ebMichael Lentine } 98375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 98389bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt skip_call |= validatePrimaryCommandBuffer(dev_data, pCB, "vkCmdExecuteComands", VALIDATION_ERROR_00163); 983929f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_EXECUTECOMMANDS, "vkCmdExecuteComands()"); 98401ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_EXECUTECOMMANDS); 98415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9842b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 9843cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.CmdExecuteCommands(commandBuffer, commandBuffersCount, pCommandBuffers); 98445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 98455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9846bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL MapMemory(VkDevice device, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size, VkFlags flags, 9847bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski void **ppData) { 984856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 98495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9850e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool skip_call = false; 98515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 9852b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 98539a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *mem_info = GetMemObjInfo(dev_data, mem); 9854cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis if (mem_info) { 9855f541bf53dee6daf82a4c8304354eac599a884d29Tobin Ehlis // TODO : This could me more fine-grained to track just region that is valid 9856f541bf53dee6daf82a4c8304354eac599a884d29Tobin Ehlis mem_info->global_valid = true; 9857623548a271287ae55415e45e3c654ee66d4e79ffTobin Ehlis auto end_offset = (VK_WHOLE_SIZE == size) ? mem_info->alloc_info.allocationSize - 1 : offset + size - 1; 9858c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski skip_call |= ValidateMapImageLayouts(dev_data, device, mem_info, offset, end_offset); 9859cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis // TODO : Do we need to create new "bound_range" for the mapped range? 9860623548a271287ae55415e45e3c654ee66d4e79ffTobin Ehlis SetMemRangesValid(dev_data, mem_info, offset, end_offset); 9861cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis if ((dev_data->phys_dev_mem_props.memoryTypes[mem_info->alloc_info.memoryTypeIndex].propertyFlags & 9862b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0) { 98632fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen skip_call = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 98642fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen (uint64_t)mem, __LINE__, VALIDATION_ERROR_00629, "MEM", 98652fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen "Mapping Memory without VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT set: mem obj 0x%" PRIxLEAST64 ". %s", 98662fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen (uint64_t)mem, validation_error_map[VALIDATION_ERROR_00629]); 98675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 98685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9869f57fc64ac43691ad98e1713886b345465573070aTobin Ehlis skip_call |= ValidateMapMemRange(dev_data, mem, offset, size); 9870b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 98715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9872e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves if (!skip_call) { 98734a0754042cf090e131e9e769d8a3633c228625beChris Forbes result = dev_data->dispatch_table.MapMemory(device, mem, offset, size, flags, ppData); 98747c0012acb5327961b0a5191434a08e5fa788786dTobin Ehlis if (VK_SUCCESS == result) { 98757c0012acb5327961b0a5191434a08e5fa788786dTobin Ehlis lock.lock(); 9876cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis // TODO : What's the point of this range? See comment on creating new "bound_range" above, which may replace this 98777c0012acb5327961b0a5191434a08e5fa788786dTobin Ehlis storeMemRanges(dev_data, mem, offset, size); 98785f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski initializeAndTrackMemory(dev_data, mem, offset, size, ppData); 98797c0012acb5327961b0a5191434a08e5fa788786dTobin Ehlis lock.unlock(); 98807c0012acb5327961b0a5191434a08e5fa788786dTobin Ehlis } 98815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 98825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 98835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 98845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 988589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL UnmapMemory(VkDevice device, VkDeviceMemory mem) { 988656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 988783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 98885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9889b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 98908860b85a52096f9f9b28616bc37feed505497a54Chris Forbes skip_call |= deleteMemRanges(dev_data, mem); 9891b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 989283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis if (!skip_call) { 98934a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.UnmapMemory(device, mem); 98945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 98955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 98965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 98978860b85a52096f9f9b28616bc37feed505497a54Chris Forbesstatic bool validateMemoryIsMapped(layer_data *dev_data, const char *funcName, uint32_t memRangeCount, 9898e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves const VkMappedMemoryRange *pMemRanges) { 9899c7ee6f2fe100c1aacfaa0872832717c906bb8a4aMark Lobodzinski bool skip = false; 99005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < memRangeCount; ++i) { 99019a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto mem_info = GetMemObjInfo(dev_data, pMemRanges[i].memory); 990257fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis if (mem_info) { 9903f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski if (pMemRanges[i].size == VK_WHOLE_SIZE) { 9904f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski if (mem_info->mem_range.offset > pMemRanges[i].offset) { 9905cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 9906cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, (uint64_t)pMemRanges[i].memory, __LINE__, 9907cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VALIDATION_ERROR_00643, "MEM", "%s: Flush/Invalidate offset (" PRINTF_SIZE_T_SPECIFIER 9908cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ") is less than Memory Object's offset " 9909cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "(" PRINTF_SIZE_T_SPECIFIER "). %s", 9910cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski funcName, static_cast<size_t>(pMemRanges[i].offset), 9911cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski static_cast<size_t>(mem_info->mem_range.offset), validation_error_map[VALIDATION_ERROR_00643]); 9912f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski } 9913f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski } else { 9914f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski const uint64_t data_end = (mem_info->mem_range.size == VK_WHOLE_SIZE) 9915f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski ? mem_info->alloc_info.allocationSize 9916f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski : (mem_info->mem_range.offset + mem_info->mem_range.size); 9917f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski if ((mem_info->mem_range.offset > pMemRanges[i].offset) || 9918f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski (data_end < (pMemRanges[i].offset + pMemRanges[i].size))) { 9919c7ee6f2fe100c1aacfaa0872832717c906bb8a4aMark Lobodzinski skip |= 9920f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 9921f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski (uint64_t)pMemRanges[i].memory, __LINE__, VALIDATION_ERROR_00642, "MEM", 9922f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski "%s: Flush/Invalidate size or offset (" PRINTF_SIZE_T_SPECIFIER ", " PRINTF_SIZE_T_SPECIFIER 9923f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski ") exceed the Memory Object's upper-bound " 9924f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski "(" PRINTF_SIZE_T_SPECIFIER "). %s", 9925f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski funcName, static_cast<size_t>(pMemRanges[i].offset + pMemRanges[i].size), 9926f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski static_cast<size_t>(pMemRanges[i].offset), static_cast<size_t>(data_end), 9927f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski validation_error_map[VALIDATION_ERROR_00642]); 9928f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski } 99295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 99305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 99315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9932c7ee6f2fe100c1aacfaa0872832717c906bb8a4aMark Lobodzinski return skip; 99335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 99345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9935bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinskistatic bool ValidateAndCopyNoncoherentMemoryToDriver(layer_data *dev_data, uint32_t mem_range_count, 9936bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski const VkMappedMemoryRange *mem_ranges) { 9937bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski bool skip = false; 9938bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski for (uint32_t i = 0; i < mem_range_count; ++i) { 99399a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto mem_info = GetMemObjInfo(dev_data, mem_ranges[i].memory); 994057fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis if (mem_info) { 99415f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski if (mem_info->shadow_copy) { 99425f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski VkDeviceSize size = (mem_info->mem_range.size != VK_WHOLE_SIZE) 99435f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski ? mem_info->mem_range.size 9944d8a53ade6b5501256798a8b4ec0bc14f72adc1faTobin Ehlis : (mem_info->alloc_info.allocationSize - mem_info->mem_range.offset); 99455f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski char *data = static_cast<char *>(mem_info->shadow_copy); 99465f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski for (uint64_t j = 0; j < mem_info->shadow_pad_size; ++j) { 99475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (data[j] != NoncoherentMemoryFillValue) { 9948bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 9949bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, (uint64_t)mem_ranges[i].memory, __LINE__, 9950bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski MEMTRACK_INVALID_MAP, "MEM", "Memory underflow was detected on mem obj 0x%" PRIxLEAST64, 9951bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski (uint64_t)mem_ranges[i].memory); 99525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 99535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 99545f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski for (uint64_t j = (size + mem_info->shadow_pad_size); j < (2 * mem_info->shadow_pad_size + size); ++j) { 99555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (data[j] != NoncoherentMemoryFillValue) { 9956bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 9957bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, (uint64_t)mem_ranges[i].memory, __LINE__, 9958bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski MEMTRACK_INVALID_MAP, "MEM", "Memory overflow was detected on mem obj 0x%" PRIxLEAST64, 9959bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski (uint64_t)mem_ranges[i].memory); 99605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 99615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 99625f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski memcpy(mem_info->p_driver_data, static_cast<void *>(data + mem_info->shadow_pad_size), (size_t)(size)); 99635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 99645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 99655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9966bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski return skip; 99675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 99685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9969bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinskistatic void CopyNoncoherentMemoryFromDriver(layer_data *dev_data, uint32_t mem_range_count, const VkMappedMemoryRange *mem_ranges) { 9970bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski for (uint32_t i = 0; i < mem_range_count; ++i) { 99719a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto mem_info = GetMemObjInfo(dev_data, mem_ranges[i].memory); 99725f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski if (mem_info && mem_info->shadow_copy) { 99735f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski VkDeviceSize size = (mem_info->mem_range.size != VK_WHOLE_SIZE) 99745f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski ? mem_info->mem_range.size 99755f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski : (mem_info->alloc_info.allocationSize - mem_ranges[i].offset); 99765f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski char *data = static_cast<char *>(mem_info->shadow_copy); 99775f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski memcpy(data + mem_info->shadow_pad_size, mem_info->p_driver_data, (size_t)(size)); 99789e21e56fc23ade48efd3752d2e2729895eb90349Mark Lobodzinski } 99799e21e56fc23ade48efd3752d2e2729895eb90349Mark Lobodzinski } 99809e21e56fc23ade48efd3752d2e2729895eb90349Mark Lobodzinski} 99819e21e56fc23ade48efd3752d2e2729895eb90349Mark Lobodzinski 9982ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinskistatic bool ValidateMappedMemoryRangeDeviceLimits(layer_data *dev_data, const char *func_name, uint32_t mem_range_count, 9983ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski const VkMappedMemoryRange *mem_ranges) { 9984ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski bool skip = false; 9985ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski for (uint32_t i = 0; i < mem_range_count; ++i) { 9986ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski uint64_t atom_size = dev_data->phys_dev_properties.properties.limits.nonCoherentAtomSize; 9987ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski if (vk_safe_modulo(mem_ranges[i].offset, atom_size) != 0) { 9988ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 9989ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski __LINE__, VALIDATION_ERROR_00644, "MEM", 9990ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski "%s: Offset in pMemRanges[%d] is 0x%" PRIxLEAST64 9991ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski ", which is not a multiple of VkPhysicalDeviceLimits::nonCoherentAtomSize (0x%" PRIxLEAST64 "). %s", 9992ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski func_name, i, mem_ranges[i].offset, atom_size, validation_error_map[VALIDATION_ERROR_00644]); 9993ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski } 9994ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski if ((mem_ranges[i].size != VK_WHOLE_SIZE) && (vk_safe_modulo(mem_ranges[i].size, atom_size) != 0)) { 9995ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 9996ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski __LINE__, VALIDATION_ERROR_00645, "MEM", 9997ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski "%s: Size in pMemRanges[%d] is 0x%" PRIxLEAST64 9998ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski ", which is not a multiple of VkPhysicalDeviceLimits::nonCoherentAtomSize (0x%" PRIxLEAST64 "). %s", 9999ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski func_name, i, mem_ranges[i].size, atom_size, validation_error_map[VALIDATION_ERROR_00645]); 10000ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski } 10001ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski } 10002ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski return skip; 10003ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski} 10004ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski 1000580e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinskistatic bool PreCallValidateFlushMappedMemoryRanges(layer_data *dev_data, uint32_t mem_range_count, 1000680e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski const VkMappedMemoryRange *mem_ranges) { 1000780e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski bool skip = false; 1000880e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski std::lock_guard<std::mutex> lock(global_lock); 1000980e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski skip |= ValidateAndCopyNoncoherentMemoryToDriver(dev_data, mem_range_count, mem_ranges); 1001080e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski skip |= validateMemoryIsMapped(dev_data, "vkFlushMappedMemoryRanges", mem_range_count, mem_ranges); 1001180e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski return skip; 1001280e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski} 1001380e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski 10014bba0de708d942e9a2187158915856995db1c5a4dMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL FlushMappedMemoryRanges(VkDevice device, uint32_t memRangeCount, 10015bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski const VkMappedMemoryRange *pMemRanges) { 100165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 1001756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 100185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1001980e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski if (!PreCallValidateFlushMappedMemoryRanges(dev_data, memRangeCount, pMemRanges)) { 100204a0754042cf090e131e9e769d8a3633c228625beChris Forbes result = dev_data->dispatch_table.FlushMappedMemoryRanges(device, memRangeCount, pMemRanges); 100215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 100225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 100235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 100245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1002580e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinskistatic bool PreCallValidateInvalidateMappedMemoryRanges(layer_data *dev_data, uint32_t mem_range_count, 1002680e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski const VkMappedMemoryRange *mem_ranges) { 1002780e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski bool skip = false; 1002880e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski std::lock_guard<std::mutex> lock(global_lock); 1002980e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski skip |= validateMemoryIsMapped(dev_data, "vkInvalidateMappedMemoryRanges", mem_range_count, mem_ranges); 1003080e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski return skip; 1003180e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski} 1003280e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski 1003380e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinskistatic void PostCallRecordInvalidateMappedMemoryRanges(layer_data *dev_data, uint32_t mem_range_count, 1003480e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski const VkMappedMemoryRange *mem_ranges) { 1003580e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski std::lock_guard<std::mutex> lock(global_lock); 1003680e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski // Update our shadow copy with modified driver data 1003780e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski CopyNoncoherentMemoryFromDriver(dev_data, mem_range_count, mem_ranges); 1003880e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski} 1003980e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski 10040bba0de708d942e9a2187158915856995db1c5a4dMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL InvalidateMappedMemoryRanges(VkDevice device, uint32_t memRangeCount, 10041bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski const VkMappedMemoryRange *pMemRanges) { 100425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 1004356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 100445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1004580e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski if (!PreCallValidateInvalidateMappedMemoryRanges(dev_data, memRangeCount, pMemRanges)) { 100464a0754042cf090e131e9e769d8a3633c228625beChris Forbes result = dev_data->dispatch_table.InvalidateMappedMemoryRanges(device, memRangeCount, pMemRanges); 1004780e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski if (result == VK_SUCCESS) { 1004880e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski PostCallRecordInvalidateMappedMemoryRanges(dev_data, memRangeCount, pMemRanges); 1004980e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski } 100505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 100515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 100525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 100535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10054341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Strattonstatic bool PreCallValidateBindImageMemory(layer_data *dev_data, VkImage image, VkDeviceMemory mem, VkDeviceSize memoryOffset) { 100550109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski bool skip = false; 10056b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 10057341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton 100589a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_state = GetImageState(dev_data, image); 100591facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis if (image_state) { 1006094c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis // Track objects tied to memory 1006147aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski uint64_t image_handle = reinterpret_cast<uint64_t &>(image); 10062c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton skip = ValidateSetMemBinding(dev_data, mem, image_handle, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, "vkBindImageMemory()"); 10063ff3ef1181960319d2268e82dae075726f650c553Tobin Ehlis if (!image_state->memory_requirements_checked) { 10064ff3ef1181960319d2268e82dae075726f650c553Tobin Ehlis // There's not an explicit requirement in the spec to call vkGetImageMemoryRequirements() prior to calling 10065341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton // BindImageMemory but it's implied in that memory being bound must conform with VkMemoryRequirements from 10066341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton // vkGetImageMemoryRequirements() 100670109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 100680109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski image_handle, __LINE__, DRAWSTATE_INVALID_IMAGE, "DS", 100690109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski "vkBindImageMemory(): Binding memory to image 0x%" PRIxLEAST64 100700109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski " but vkGetImageMemoryRequirements() has not been called on that image.", 100710109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski image_handle); 10072ff3ef1181960319d2268e82dae075726f650c553Tobin Ehlis // Make the call for them so we can verify the state 10073ff3ef1181960319d2268e82dae075726f650c553Tobin Ehlis lock.unlock(); 10074341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton dev_data->dispatch_table.GetImageMemoryRequirements(dev_data->device, image, &image_state->requirements); 10075ff3ef1181960319d2268e82dae075726f650c553Tobin Ehlis lock.lock(); 10076ff3ef1181960319d2268e82dae075726f650c553Tobin Ehlis } 1007747aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski 1007847aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski // Track and validate bound memory range information 100799a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto mem_info = GetMemObjInfo(dev_data, mem); 1008057fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis if (mem_info) { 100810109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski skip |= InsertImageMemoryRange(dev_data, image, mem_info, memoryOffset, image_state->requirements, 1008274300755ed9ec780d6073af71e47f201217008d6Cort Stratton image_state->createInfo.tiling == VK_IMAGE_TILING_LINEAR, "vkBindImageMemory()"); 1008374300755ed9ec780d6073af71e47f201217008d6Cort Stratton skip |= ValidateMemoryTypes(dev_data, mem_info, image_state->requirements.memoryTypeBits, "vkBindImageMemory()", 100840109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski VALIDATION_ERROR_00806); 1008547aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski } 10086341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton } 10087341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton return skip; 10088341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton} 1008947aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski 10090341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Strattonstatic void PostCallRecordBindImageMemory(layer_data *dev_data, VkImage image, VkDeviceMemory mem, VkDeviceSize memoryOffset) { 10091341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton std::unique_lock<std::mutex> lock(global_lock); 10092341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton auto image_state = GetImageState(dev_data, image); 10093341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton if (image_state) { 10094c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton // Track objects tied to memory 10095c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton uint64_t image_handle = reinterpret_cast<uint64_t &>(image); 10096c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton SetMemBinding(dev_data, mem, image_handle, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, "vkBindImageMemory()"); 10097c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton 10098341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton image_state->binding.mem = mem; 10099341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton image_state->binding.offset = memoryOffset; 10100341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton image_state->binding.size = image_state->requirements.size; 10101341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton } 10102341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton} 10103341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton 10104341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort StrattonVKAPI_ATTR VkResult VKAPI_CALL BindImageMemory(VkDevice device, VkImage image, VkDeviceMemory mem, VkDeviceSize memoryOffset) { 10105341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 10106341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 10107341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton bool skip = PreCallValidateBindImageMemory(dev_data, image, mem, memoryOffset); 10108341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton if (!skip) { 10109341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton result = dev_data->dispatch_table.BindImageMemory(device, image, mem, memoryOffset); 10110341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton if (result == VK_SUCCESS) { 10111341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton PostCallRecordBindImageMemory(dev_data, image, mem, memoryOffset); 1011294c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis } 101135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 101145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 101155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 101165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1011789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL SetEvent(VkDevice device, VkEvent event) { 101183ee1d6057ee6c49b9dbbeb067b7fd149bdba7b5cTobin Ehlis bool skip_call = false; 101193ee1d6057ee6c49b9dbbeb067b7fd149bdba7b5cTobin Ehlis VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 1012056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 10121b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 101229a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto event_state = GetEventNode(dev_data, event); 101234710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis if (event_state) { 101244710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis event_state->needsSignaled = false; 101254710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis event_state->stageMask = VK_PIPELINE_STAGE_HOST_BIT; 101264710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis if (event_state->write_in_use) { 101273ee1d6057ee6c49b9dbbeb067b7fd149bdba7b5cTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT, 101283ee1d6057ee6c49b9dbbeb067b7fd149bdba7b5cTobin Ehlis reinterpret_cast<const uint64_t &>(event), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS", 10129414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller "Cannot call vkSetEvent() on event 0x%" PRIxLEAST64 " that is already in use by a command buffer.", 101303ee1d6057ee6c49b9dbbeb067b7fd149bdba7b5cTobin Ehlis reinterpret_cast<const uint64_t &>(event)); 101313ee1d6057ee6c49b9dbbeb067b7fd149bdba7b5cTobin Ehlis } 101323ee1d6057ee6c49b9dbbeb067b7fd149bdba7b5cTobin Ehlis } 10133b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 101346fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis // Host setting event is visible to all queues immediately so update stageMask for any queue that's seen this event 101356fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis // TODO : For correctness this needs separate fix to verify that app doesn't make incorrect assumptions about the 101366fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis // ordering of this command in relation to vkCmd[Set|Reset]Events (see GH297) 101376fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis for (auto queue_data : dev_data->queueMap) { 101386fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis auto event_entry = queue_data.second.eventToStageMap.find(event); 101396fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis if (event_entry != queue_data.second.eventToStageMap.end()) { 101406fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis event_entry->second |= VK_PIPELINE_STAGE_HOST_BIT; 101416fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis } 101426fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis } 10143cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) result = dev_data->dispatch_table.SetEvent(device, event); 101445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 101455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 101465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10147bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL QueueBindSparse(VkQueue queue, uint32_t bindInfoCount, const VkBindSparseInfo *pBindInfo, 10148bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkFence fence) { 1014956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map); 101505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 10151e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool skip_call = false; 10152b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 101539a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pFence = GetFenceNode(dev_data, fence); 101549a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pQueue = GetQueueState(dev_data, queue); 10155651d92815dfff917308137bb67aacccc4f60df86Chris Forbes 101564b38d3aa8b6be6a7f5bebb472ab439da0562824fTobin Ehlis // First verify that fence is not in use 10157651d92815dfff917308137bb67aacccc4f60df86Chris Forbes skip_call |= ValidateFenceForSubmit(dev_data, pFence); 10158651d92815dfff917308137bb67aacccc4f60df86Chris Forbes 101599867daedbf52debc77d6568162ee21e071699b80Chris Forbes if (pFence) { 101609867daedbf52debc77d6568162ee21e071699b80Chris Forbes SubmitFence(pQueue, pFence, bindInfoCount); 101614b38d3aa8b6be6a7f5bebb472ab439da0562824fTobin Ehlis } 10162651d92815dfff917308137bb67aacccc4f60df86Chris Forbes 101631344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis for (uint32_t bindIdx = 0; bindIdx < bindInfoCount; ++bindIdx) { 101641344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis const VkBindSparseInfo &bindInfo = pBindInfo[bindIdx]; 101655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Track objects tied to memory 101661344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis for (uint32_t j = 0; j < bindInfo.bufferBindCount; j++) { 101671344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis for (uint32_t k = 0; k < bindInfo.pBufferBinds[j].bindCount; k++) { 10168f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis auto sparse_binding = bindInfo.pBufferBinds[j].pBinds[k]; 10169f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis if (SetSparseMemBinding(dev_data, {sparse_binding.memory, sparse_binding.memoryOffset, sparse_binding.size}, 10170f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis (uint64_t)bindInfo.pBufferBinds[j].buffer, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, 10171f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis "vkQueueBindSparse")) 10172e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves skip_call = true; 101735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 101745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 101751344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis for (uint32_t j = 0; j < bindInfo.imageOpaqueBindCount; j++) { 101761344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis for (uint32_t k = 0; k < bindInfo.pImageOpaqueBinds[j].bindCount; k++) { 10177f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis auto sparse_binding = bindInfo.pImageOpaqueBinds[j].pBinds[k]; 10178f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis if (SetSparseMemBinding(dev_data, {sparse_binding.memory, sparse_binding.memoryOffset, sparse_binding.size}, 10179f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis (uint64_t)bindInfo.pImageOpaqueBinds[j].image, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 10180f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis "vkQueueBindSparse")) 10181e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves skip_call = true; 101825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 101835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 101841344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis for (uint32_t j = 0; j < bindInfo.imageBindCount; j++) { 101851344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis for (uint32_t k = 0; k < bindInfo.pImageBinds[j].bindCount; k++) { 10186f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis auto sparse_binding = bindInfo.pImageBinds[j].pBinds[k]; 10187f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis // TODO: This size is broken for non-opaque bindings, need to update to comprehend full sparse binding data 10188f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis VkDeviceSize size = sparse_binding.extent.depth * sparse_binding.extent.height * sparse_binding.extent.width * 4; 10189f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis if (SetSparseMemBinding(dev_data, {sparse_binding.memory, sparse_binding.memoryOffset, size}, 10190f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis (uint64_t)bindInfo.pImageBinds[j].image, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 10191f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis "vkQueueBindSparse")) 10192e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves skip_call = true; 101935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 101945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 101959867daedbf52debc77d6568162ee21e071699b80Chris Forbes 101969867daedbf52debc77d6568162ee21e071699b80Chris Forbes std::vector<SEMAPHORE_WAIT> semaphore_waits; 101979867daedbf52debc77d6568162ee21e071699b80Chris Forbes std::vector<VkSemaphore> semaphore_signals; 101981344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis for (uint32_t i = 0; i < bindInfo.waitSemaphoreCount; ++i) { 1019901a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes VkSemaphore semaphore = bindInfo.pWaitSemaphores[i]; 102009a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pSemaphore = GetSemaphoreNode(dev_data, semaphore); 1020101a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes if (pSemaphore) { 1020201a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes if (pSemaphore->signaled) { 102039867daedbf52debc77d6568162ee21e071699b80Chris Forbes if (pSemaphore->signaler.first != VK_NULL_HANDLE) { 102049867daedbf52debc77d6568162ee21e071699b80Chris Forbes semaphore_waits.push_back({semaphore, pSemaphore->signaler.first, pSemaphore->signaler.second}); 102059867daedbf52debc77d6568162ee21e071699b80Chris Forbes pSemaphore->in_use.fetch_add(1); 102069867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 102079867daedbf52debc77d6568162ee21e071699b80Chris Forbes pSemaphore->signaler.first = VK_NULL_HANDLE; 1020801a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes pSemaphore->signaled = false; 102091344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis } else { 10210226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis skip_call |= log_msg( 10211226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT, 10212226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis reinterpret_cast<const uint64_t &>(semaphore), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS", 10213226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "vkQueueBindSparse: Queue 0x%p is waiting on semaphore 0x%" PRIx64 " that has no way to be signaled.", 10214226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis queue, reinterpret_cast<const uint64_t &>(semaphore)); 102155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 102165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 102175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 102181344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis for (uint32_t i = 0; i < bindInfo.signalSemaphoreCount; ++i) { 1021901a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes VkSemaphore semaphore = bindInfo.pSignalSemaphores[i]; 102209a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pSemaphore = GetSemaphoreNode(dev_data, semaphore); 1022101a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes if (pSemaphore) { 1022201a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes if (pSemaphore->signaled) { 102235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis skip_call = 102245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT, 102251344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis reinterpret_cast<const uint64_t &>(semaphore), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS", 10226226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "vkQueueBindSparse: Queue 0x%p is signaling semaphore 0x%" PRIx64 102271344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis ", but that semaphore is already signaled.", 10228226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis queue, reinterpret_cast<const uint64_t &>(semaphore)); 10229bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski } else { 102309867daedbf52debc77d6568162ee21e071699b80Chris Forbes pSemaphore->signaler.first = queue; 102319867daedbf52debc77d6568162ee21e071699b80Chris Forbes pSemaphore->signaler.second = pQueue->seq + pQueue->submissions.size() + 1; 102329867daedbf52debc77d6568162ee21e071699b80Chris Forbes pSemaphore->signaled = true; 102339867daedbf52debc77d6568162ee21e071699b80Chris Forbes pSemaphore->in_use.fetch_add(1); 102349867daedbf52debc77d6568162ee21e071699b80Chris Forbes semaphore_signals.push_back(semaphore); 102359867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 102365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 102375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 102389867daedbf52debc77d6568162ee21e071699b80Chris Forbes 10239bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pQueue->submissions.emplace_back(std::vector<VkCommandBuffer>(), semaphore_waits, semaphore_signals, 102409867daedbf52debc77d6568162ee21e071699b80Chris Forbes bindIdx == bindInfoCount - 1 ? fence : VK_NULL_HANDLE); 102415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 102429867daedbf52debc77d6568162ee21e071699b80Chris Forbes 102439867daedbf52debc77d6568162ee21e071699b80Chris Forbes if (pFence && !bindInfoCount) { 102449867daedbf52debc77d6568162ee21e071699b80Chris Forbes // No work to do, just dropping a fence in the queue by itself. 10245bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pQueue->submissions.emplace_back(std::vector<VkCommandBuffer>(), std::vector<SEMAPHORE_WAIT>(), std::vector<VkSemaphore>(), 102469867daedbf52debc77d6568162ee21e071699b80Chris Forbes fence); 102479867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 102489867daedbf52debc77d6568162ee21e071699b80Chris Forbes 10249b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 102505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10251cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) return dev_data->dispatch_table.QueueBindSparse(queue, bindInfoCount, pBindInfo, fence); 102525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 102535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 102545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 102555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1025689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateSemaphore(VkDevice device, const VkSemaphoreCreateInfo *pCreateInfo, 1025789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkSemaphore *pSemaphore) { 1025856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 102594a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateSemaphore(device, pCreateInfo, pAllocator, pSemaphore); 102605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (result == VK_SUCCESS) { 10261b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 10262bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SEMAPHORE_NODE *sNode = &dev_data->semaphoreMap[*pSemaphore]; 102639867daedbf52debc77d6568162ee21e071699b80Chris Forbes sNode->signaler.first = VK_NULL_HANDLE; 102649867daedbf52debc77d6568162ee21e071699b80Chris Forbes sNode->signaler.second = 0; 102651344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis sNode->signaled = false; 102665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 102675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 102685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 102695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10270bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateEvent(VkDevice device, const VkEventCreateInfo *pCreateInfo, 10271bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkEvent *pEvent) { 1027256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 102734a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateEvent(device, pCreateInfo, pAllocator, pEvent); 102745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (result == VK_SUCCESS) { 10275b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 102765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->eventMap[*pEvent].needsSignaled = false; 10277293ecfc5e69ed3978a8c04518166d828294870a4Tony Barbour dev_data->eventMap[*pEvent].write_in_use = 0; 102785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->eventMap[*pEvent].stageMask = VkPipelineStageFlags(0); 102795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 102805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 102815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 102825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 102839ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinskistatic bool PreCallValidateCreateSwapchainKHR(layer_data *dev_data, const char *func_name, 102849ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski VkSwapchainCreateInfoKHR const *pCreateInfo, SURFACE_STATE *surface_state, 102859ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski SWAPCHAIN_NODE *old_swapchain_state) { 10286d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes auto most_recent_swapchain = surface_state->swapchain ? surface_state->swapchain : surface_state->old_swapchain; 10287d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes 102884bd5f453535de3d3423ff1f9995b4acb15f791d2Chris Forbes // TODO: revisit this. some of these rules are being relaxed. 10289d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes if (most_recent_swapchain != old_swapchain_state || (surface_state->old_swapchain && surface_state->swapchain)) { 10290d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 10291d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes reinterpret_cast<uint64_t>(dev_data->device), __LINE__, DRAWSTATE_SWAPCHAIN_ALREADY_EXISTS, "DS", 102929ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s: surface has an existing swapchain other than oldSwapchain", func_name)) 10293d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes return true; 10294d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes } 10295d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes if (old_swapchain_state && old_swapchain_state->createInfo.surface != pCreateInfo->surface) { 10296d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 10297d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes reinterpret_cast<uint64_t const &>(pCreateInfo->oldSwapchain), __LINE__, DRAWSTATE_SWAPCHAIN_WRONG_SURFACE, 102989ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "DS", "%s: pCreateInfo->oldSwapchain's surface is not pCreateInfo->surface", func_name)) 10299d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes return true; 10300d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes } 103019a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto physical_device_state = GetPhysicalDeviceState(dev_data->instance_data, dev_data->physical_device); 103027de258f87ca1192db116a66b209253793d276ebcChris Forbes if (physical_device_state->vkGetPhysicalDeviceSurfaceCapabilitiesKHRState == UNCALLED) { 103037de258f87ca1192db116a66b209253793d276ebcChris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 103047de258f87ca1192db116a66b209253793d276ebcChris Forbes reinterpret_cast<uint64_t>(dev_data->physical_device), __LINE__, DRAWSTATE_SWAPCHAIN_CREATE_BEFORE_QUERY, "DS", 103059ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s: surface capabilities not retrieved for this physical device", func_name)) 103067de258f87ca1192db116a66b209253793d276ebcChris Forbes return true; 10307cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else { // have valid capabilities 103085c99b4daed164798f307244c9bde17b4f66014fbChris Forbes auto &capabilities = physical_device_state->surfaceCapabilities; 103099ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // Validate pCreateInfo->minImageCount against VkSurfaceCapabilitiesKHR::{min|max}ImageCount: 103102fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen if (pCreateInfo->minImageCount < capabilities.minImageCount) { 103112fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 103122fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t>(dev_data->device), __LINE__, VALIDATION_ERROR_02331, "DS", 103139ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s called with minImageCount = %d, which is outside the bounds returned " 103142fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen "by vkGetPhysicalDeviceSurfaceCapabilitiesKHR() (i.e. minImageCount = %d, maxImageCount = %d). %s", 103159ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski func_name, pCreateInfo->minImageCount, capabilities.minImageCount, capabilities.maxImageCount, 103162fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen validation_error_map[VALIDATION_ERROR_02331])) 103172fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen return true; 103182fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen } 103192fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen 103202fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen if ((capabilities.maxImageCount > 0) && (pCreateInfo->minImageCount > capabilities.maxImageCount)) { 103215c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 103222fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t>(dev_data->device), __LINE__, VALIDATION_ERROR_02332, "DS", 103239ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s called with minImageCount = %d, which is outside the bounds returned " 103242fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen "by vkGetPhysicalDeviceSurfaceCapabilitiesKHR() (i.e. minImageCount = %d, maxImageCount = %d). %s", 103259ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski func_name, pCreateInfo->minImageCount, capabilities.minImageCount, capabilities.maxImageCount, 103262fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen validation_error_map[VALIDATION_ERROR_02332])) 103275c99b4daed164798f307244c9bde17b4f66014fbChris Forbes return true; 103285c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 103292fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen 103309ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // Validate pCreateInfo->imageExtent against VkSurfaceCapabilitiesKHR::{current|min|max}ImageExtent: 103312e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill if ((capabilities.currentExtent.width == kSurfaceSizeFromSwapchain) && 103322e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill ((pCreateInfo->imageExtent.width < capabilities.minImageExtent.width) || 103332e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill (pCreateInfo->imageExtent.width > capabilities.maxImageExtent.width) || 103342e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill (pCreateInfo->imageExtent.height < capabilities.minImageExtent.height) || 103352e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill (pCreateInfo->imageExtent.height > capabilities.maxImageExtent.height))) { 103365c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 103372fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t>(dev_data->device), __LINE__, VALIDATION_ERROR_02334, "DS", 103389ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s called with imageExtent = (%d,%d), which is outside the bounds returned by " 103399ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "vkGetPhysicalDeviceSurfaceCapabilitiesKHR(): currentExtent = (%d,%d), minImageExtent = (%d,%d), " 103409ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "maxImageExtent = (%d,%d). %s", 103419ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski func_name, pCreateInfo->imageExtent.width, pCreateInfo->imageExtent.height, 103429ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski capabilities.currentExtent.width, capabilities.currentExtent.height, capabilities.minImageExtent.width, 103439ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski capabilities.minImageExtent.height, capabilities.maxImageExtent.width, capabilities.maxImageExtent.height, 103442fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen validation_error_map[VALIDATION_ERROR_02334])) 103455c99b4daed164798f307244c9bde17b4f66014fbChris Forbes return true; 103465c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 103472e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill if ((capabilities.currentExtent.width != kSurfaceSizeFromSwapchain) && 103482e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill ((pCreateInfo->imageExtent.width != capabilities.currentExtent.width) || 103492e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill (pCreateInfo->imageExtent.height != capabilities.currentExtent.height))) { 103505c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 103512fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t>(dev_data->device), __LINE__, VALIDATION_ERROR_02334, "DS", 103529ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s called with imageExtent = (%d,%d), which is not equal to the currentExtent = (%d,%d) returned by " 103539ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "vkGetPhysicalDeviceSurfaceCapabilitiesKHR(). %s", 103549ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski func_name, pCreateInfo->imageExtent.width, pCreateInfo->imageExtent.height, 103559ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski capabilities.currentExtent.width, capabilities.currentExtent.height, 103562fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen validation_error_map[VALIDATION_ERROR_02334])) 103575c99b4daed164798f307244c9bde17b4f66014fbChris Forbes return true; 103585c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 103599ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // pCreateInfo->preTransform should have exactly one bit set, and that bit must also be set in 103609ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // VkSurfaceCapabilitiesKHR::supportedTransforms. 103615c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (!pCreateInfo->preTransform || (pCreateInfo->preTransform & (pCreateInfo->preTransform - 1)) || 103625c99b4daed164798f307244c9bde17b4f66014fbChris Forbes !(pCreateInfo->preTransform & capabilities.supportedTransforms)) { 103639ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // This is an error situation; one for which we'd like to give the developer a helpful, multi-line error message. Build 103649ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // it up a little at a time, and then log it: 103655c99b4daed164798f307244c9bde17b4f66014fbChris Forbes std::string errorString = ""; 103665c99b4daed164798f307244c9bde17b4f66014fbChris Forbes char str[1024]; 103675c99b4daed164798f307244c9bde17b4f66014fbChris Forbes // Here's the first part of the message: 103689ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski sprintf(str, "%s called with a non-supported pCreateInfo->preTransform (i.e. %s). Supported values are:\n", func_name, 103695c99b4daed164798f307244c9bde17b4f66014fbChris Forbes string_VkSurfaceTransformFlagBitsKHR(pCreateInfo->preTransform)); 103705c99b4daed164798f307244c9bde17b4f66014fbChris Forbes errorString += str; 103715c99b4daed164798f307244c9bde17b4f66014fbChris Forbes for (int i = 0; i < 32; i++) { 103725c99b4daed164798f307244c9bde17b4f66014fbChris Forbes // Build up the rest of the message: 103735c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if ((1 << i) & capabilities.supportedTransforms) { 103745c99b4daed164798f307244c9bde17b4f66014fbChris Forbes const char *newStr = string_VkSurfaceTransformFlagBitsKHR((VkSurfaceTransformFlagBitsKHR)(1 << i)); 103755c99b4daed164798f307244c9bde17b4f66014fbChris Forbes sprintf(str, " %s\n", newStr); 103765c99b4daed164798f307244c9bde17b4f66014fbChris Forbes errorString += str; 103775c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 103785c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 103795c99b4daed164798f307244c9bde17b4f66014fbChris Forbes // Log the message that we've built up: 103805c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 103812fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t &>(dev_data->device), __LINE__, VALIDATION_ERROR_02339, "DS", "%s. %s", 103822fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen errorString.c_str(), validation_error_map[VALIDATION_ERROR_02339])) 103835c99b4daed164798f307244c9bde17b4f66014fbChris Forbes return true; 103845c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 103857b0d28d116977b91892f354e002edd760bdb86cbChris Forbes 103869ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // pCreateInfo->compositeAlpha should have exactly one bit set, and that bit must also be set in 103879ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // VkSurfaceCapabilitiesKHR::supportedCompositeAlpha 103885c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (!pCreateInfo->compositeAlpha || (pCreateInfo->compositeAlpha & (pCreateInfo->compositeAlpha - 1)) || 103895c99b4daed164798f307244c9bde17b4f66014fbChris Forbes !((pCreateInfo->compositeAlpha) & capabilities.supportedCompositeAlpha)) { 103909ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // This is an error situation; one for which we'd like to give the developer a helpful, multi-line error message. Build 103919ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // it up a little at a time, and then log it: 103925c99b4daed164798f307244c9bde17b4f66014fbChris Forbes std::string errorString = ""; 103935c99b4daed164798f307244c9bde17b4f66014fbChris Forbes char str[1024]; 103945c99b4daed164798f307244c9bde17b4f66014fbChris Forbes // Here's the first part of the message: 103959ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski sprintf(str, "%s called with a non-supported pCreateInfo->compositeAlpha (i.e. %s). Supported values are:\n", 103969ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski func_name, string_VkCompositeAlphaFlagBitsKHR(pCreateInfo->compositeAlpha)); 103975c99b4daed164798f307244c9bde17b4f66014fbChris Forbes errorString += str; 103985c99b4daed164798f307244c9bde17b4f66014fbChris Forbes for (int i = 0; i < 32; i++) { 103995c99b4daed164798f307244c9bde17b4f66014fbChris Forbes // Build up the rest of the message: 104005c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if ((1 << i) & capabilities.supportedCompositeAlpha) { 104015c99b4daed164798f307244c9bde17b4f66014fbChris Forbes const char *newStr = string_VkCompositeAlphaFlagBitsKHR((VkCompositeAlphaFlagBitsKHR)(1 << i)); 104025c99b4daed164798f307244c9bde17b4f66014fbChris Forbes sprintf(str, " %s\n", newStr); 104035c99b4daed164798f307244c9bde17b4f66014fbChris Forbes errorString += str; 104045c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 104055c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 104065c99b4daed164798f307244c9bde17b4f66014fbChris Forbes // Log the message that we've built up: 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_02340, "DS", "%s. %s", 104092fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen errorString.c_str(), validation_error_map[VALIDATION_ERROR_02340])) 104105c99b4daed164798f307244c9bde17b4f66014fbChris Forbes return true; 104115c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 104129ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // Validate pCreateInfo->imageArrayLayers against VkSurfaceCapabilitiesKHR::maxImageArrayLayers: 104135c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if ((pCreateInfo->imageArrayLayers < 1) || (pCreateInfo->imageArrayLayers > capabilities.maxImageArrayLayers)) { 104145c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 104152fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t>(dev_data->device), __LINE__, VALIDATION_ERROR_02335, "DS", 104169ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s called with a non-supported imageArrayLayers (i.e. %d). Minimum value is 1, maximum value is %d. %s", 104179ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski func_name, pCreateInfo->imageArrayLayers, capabilities.maxImageArrayLayers, 104182fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen validation_error_map[VALIDATION_ERROR_02335])) 104195c99b4daed164798f307244c9bde17b4f66014fbChris Forbes return true; 104205c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 104219ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // Validate pCreateInfo->imageUsage against VkSurfaceCapabilitiesKHR::supportedUsageFlags: 104225c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (pCreateInfo->imageUsage != (pCreateInfo->imageUsage & capabilities.supportedUsageFlags)) { 104235c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 104242fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t>(dev_data->device), __LINE__, VALIDATION_ERROR_02336, "DS", 104259ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s called with a non-supported pCreateInfo->imageUsage (i.e. 0x%08x). Supported flag bits are 0x%08x. %s", 104269ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski func_name, pCreateInfo->imageUsage, capabilities.supportedUsageFlags, 104279ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski validation_error_map[VALIDATION_ERROR_02336])) 104285c99b4daed164798f307244c9bde17b4f66014fbChris Forbes return true; 104295c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 104307de258f87ca1192db116a66b209253793d276ebcChris Forbes } 10431d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes 104329ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // Validate pCreateInfo values with the results of vkGetPhysicalDeviceSurfaceFormatsKHR(): 104335faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (physical_device_state->vkGetPhysicalDeviceSurfaceFormatsKHRState != QUERY_DETAILS) { 104345faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 104355faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes reinterpret_cast<uint64_t>(dev_data->device), __LINE__, DRAWSTATE_SWAPCHAIN_CREATE_BEFORE_QUERY, "DS", 104369ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s called before calling vkGetPhysicalDeviceSurfaceFormatsKHR().", func_name)) 104375faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes return true; 104385faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } else { 104399ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // Validate pCreateInfo->imageFormat against VkSurfaceFormatKHR::format: 104405faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes bool foundFormat = false; 104415faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes bool foundColorSpace = false; 104425faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes bool foundMatch = false; 104435faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes for (auto const &format : physical_device_state->surface_formats) { 104445faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (pCreateInfo->imageFormat == format.format) { 104459ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // Validate pCreateInfo->imageColorSpace against VkSurfaceFormatKHR::colorSpace: 104465faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes foundFormat = true; 104475faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (pCreateInfo->imageColorSpace == format.colorSpace) { 104485faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes foundMatch = true; 104495faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes break; 104505faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 104515faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } else { 104525faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (pCreateInfo->imageColorSpace == format.colorSpace) { 104535faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes foundColorSpace = true; 104545faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 104555faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 104565faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 104575faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (!foundMatch) { 104585faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (!foundFormat) { 104595faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 104602fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t>(dev_data->device), __LINE__, VALIDATION_ERROR_02333, "DS", 10461bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "%s called with a non-supported pCreateInfo->imageFormat (i.e. %d). %s", func_name, 10462bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pCreateInfo->imageFormat, validation_error_map[VALIDATION_ERROR_02333])) 104632fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen return true; 104642fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen } 104652fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen if (!foundColorSpace) { 104662fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 104672fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t>(dev_data->device), __LINE__, VALIDATION_ERROR_02333, "DS", 10468bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "%s called with a non-supported pCreateInfo->imageColorSpace (i.e. %d). %s", func_name, 10469bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pCreateInfo->imageColorSpace, validation_error_map[VALIDATION_ERROR_02333])) 104705faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes return true; 104715faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 104725faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 104735faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 104745faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes 104759ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // Validate pCreateInfo values with the results of vkGetPhysicalDeviceSurfacePresentModesKHR(): 104769e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (physical_device_state->vkGetPhysicalDeviceSurfacePresentModesKHRState != QUERY_DETAILS) { 1047725002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // FIFO is required to always be supported 104789e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (pCreateInfo->presentMode != VK_PRESENT_MODE_FIFO_KHR) { 104799e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 104809ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski reinterpret_cast<uint64_t>(dev_data->device), __LINE__, DRAWSTATE_SWAPCHAIN_CREATE_BEFORE_QUERY, "DS", 104819ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s called before calling vkGetPhysicalDeviceSurfacePresentModesKHR().", func_name)) 104829e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes return true; 104839e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 104849e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } else { 104859ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // Validate pCreateInfo->presentMode against vkGetPhysicalDeviceSurfacePresentModesKHR(): 10486bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski bool foundMatch = std::find(physical_device_state->present_modes.begin(), physical_device_state->present_modes.end(), 104879e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes pCreateInfo->presentMode) != physical_device_state->present_modes.end(); 104889e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (!foundMatch) { 104899e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 104902fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t>(dev_data->device), __LINE__, VALIDATION_ERROR_02341, "DS", 104919ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s called with a non-supported presentMode (i.e. %s). %s", func_name, 104922fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen string_VkPresentModeKHR(pCreateInfo->presentMode), validation_error_map[VALIDATION_ERROR_02341])) 104939e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes return true; 104949e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 104959e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 104969e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes 10497d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes return false; 10498d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes} 10499d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes 10500261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinskistatic void PostCallRecordCreateSwapchainKHR(layer_data *dev_data, VkResult result, const VkSwapchainCreateInfoKHR *pCreateInfo, 10501261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski VkSwapchainKHR *pSwapchain, SURFACE_STATE *surface_state, 10502261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski SWAPCHAIN_NODE *old_swapchain_state) { 105035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 10504b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 10505ddc5201048319558ce66701163a4546ee957af19Chris Forbes auto swapchain_state = unique_ptr<SWAPCHAIN_NODE>(new SWAPCHAIN_NODE(pCreateInfo, *pSwapchain)); 10506ddc5201048319558ce66701163a4546ee957af19Chris Forbes surface_state->swapchain = swapchain_state.get(); 10507ddc5201048319558ce66701163a4546ee957af19Chris Forbes dev_data->device_extensions.swapchainMap[*pSwapchain] = std::move(swapchain_state); 10508ddc5201048319558ce66701163a4546ee957af19Chris Forbes } else { 10509ddc5201048319558ce66701163a4546ee957af19Chris Forbes surface_state->swapchain = nullptr; 105105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 10511ddc5201048319558ce66701163a4546ee957af19Chris Forbes // Spec requires that even if CreateSwapchainKHR fails, oldSwapchain behaves as replaced. 105125b5488456e5afa0487f95b805a2aba59b13d69f4Chris Forbes if (old_swapchain_state) { 105135b5488456e5afa0487f95b805a2aba59b13d69f4Chris Forbes old_swapchain_state->replaced = true; 105145b5488456e5afa0487f95b805a2aba59b13d69f4Chris Forbes } 10515ddc5201048319558ce66701163a4546ee957af19Chris Forbes surface_state->old_swapchain = old_swapchain_state; 10516261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski return; 10517261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski} 10518261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski 10519261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo, 10520261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchain) { 1052156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 105229a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto surface_state = GetSurfaceState(dev_data->instance_data, pCreateInfo->surface); 105239a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto old_swapchain_state = GetSwapchainNode(dev_data, pCreateInfo->oldSwapchain); 10524261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski 105259ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski if (PreCallValidateCreateSwapchainKHR(dev_data, "vkCreateSwapChainKHR()", pCreateInfo, surface_state, old_swapchain_state)) { 10526261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski return VK_ERROR_VALIDATION_FAILED_EXT; 10527261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski } 10528261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski 10529261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski VkResult result = dev_data->dispatch_table.CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain); 10530261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski 10531261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski PostCallRecordCreateSwapchainKHR(dev_data, result, pCreateInfo, pSwapchain, surface_state, old_swapchain_state); 10532ddc5201048319558ce66701163a4546ee957af19Chris Forbes 105335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 105345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 105355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10536bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks *pAllocator) { 1053756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 1053883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 105395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10540b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 105419a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto swapchain_data = GetSwapchainNode(dev_data, swapchain); 10542b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis if (swapchain_data) { 10543b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis if (swapchain_data->images.size() > 0) { 10544b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis for (auto swapchain_image : swapchain_data->images) { 105455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto image_sub = dev_data->imageSubresourceMap.find(swapchain_image); 105465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (image_sub != dev_data->imageSubresourceMap.end()) { 105475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto imgsubpair : image_sub->second) { 105485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto image_item = dev_data->imageLayoutMap.find(imgsubpair); 105495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (image_item != dev_data->imageLayoutMap.end()) { 105505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->imageLayoutMap.erase(image_item); 105515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 105525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 105535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->imageSubresourceMap.erase(image_sub); 105545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 1055583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call = 10556f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis ClearMemoryObjectBindings(dev_data, (uint64_t)swapchain_image, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT); 1055794c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis dev_data->imageMap.erase(swapchain_image); 105585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 105595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 10560ddc5201048319558ce66701163a4546ee957af19Chris Forbes 105619a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto surface_state = GetSurfaceState(dev_data->instance_data, swapchain_data->createInfo.surface); 10562ddc5201048319558ce66701163a4546ee957af19Chris Forbes if (surface_state) { 10563cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (surface_state->swapchain == swapchain_data) surface_state->swapchain = nullptr; 10564cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (surface_state->old_swapchain == swapchain_data) surface_state->old_swapchain = nullptr; 10565ddc5201048319558ce66701163a4546ee957af19Chris Forbes } 10566ddc5201048319558ce66701163a4546ee957af19Chris Forbes 105675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->device_extensions.swapchainMap.erase(swapchain); 105685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 10569b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 10570cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.DestroySwapchainKHR(device, swapchain, pAllocator); 105715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 105725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10573bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL GetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t *pCount, 10574bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkImage *pSwapchainImages) { 1057556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 105764a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.GetSwapchainImagesKHR(device, swapchain, pCount, pSwapchainImages); 105775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 105785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (result == VK_SUCCESS && pSwapchainImages != NULL) { 105795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // This should never happen and is checked by param checker. 10580cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!pCount) return result; 10581b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 105825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const size_t count = *pCount; 105839a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto swapchain_node = GetSwapchainNode(dev_data, swapchain); 10584b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis if (swapchain_node && !swapchain_node->images.empty()) { 105850801763633180d277d26a90343464bd11646056fTobin Ehlis // TODO : Not sure I like the memcmp here, but it works 105860801763633180d277d26a90343464bd11646056fTobin Ehlis const bool mismatch = (swapchain_node->images.size() != count || 105870801763633180d277d26a90343464bd11646056fTobin Ehlis memcmp(&swapchain_node->images[0], pSwapchainImages, sizeof(swapchain_node->images[0]) * count)); 105885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (mismatch) { 105895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODO: Verify against Valid Usage section of extension 105905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 105915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (uint64_t)swapchain, __LINE__, MEMTRACK_NONE, "SWAP_CHAIN", 10592414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller "vkGetSwapchainInfoKHR(0x%" PRIx64 105935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis ", VK_SWAP_CHAIN_INFO_TYPE_PERSISTENT_IMAGES_KHR) returned mismatching data", 105945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (uint64_t)(swapchain)); 105955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 105965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 105975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < *pCount; ++i) { 105985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis IMAGE_LAYOUT_NODE image_layout_node; 105995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis image_layout_node.layout = VK_IMAGE_LAYOUT_UNDEFINED; 106005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis image_layout_node.format = swapchain_node->createInfo.imageFormat; 106016d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis // Add imageMap entries for each swapchain image 106026d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis VkImageCreateInfo image_ci = {}; 106036d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis image_ci.mipLevels = 1; 106046d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis image_ci.arrayLayers = swapchain_node->createInfo.imageArrayLayers; 106056d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis image_ci.usage = swapchain_node->createInfo.imageUsage; 106066d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis image_ci.format = swapchain_node->createInfo.imageFormat; 1060741ebcb6b517b1de5ae456d46d866f5e84a96a2c5Tobin Ehlis image_ci.samples = VK_SAMPLE_COUNT_1_BIT; 106086d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis image_ci.extent.width = swapchain_node->createInfo.imageExtent.width; 106096d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis image_ci.extent.height = swapchain_node->createInfo.imageExtent.height; 106106d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis image_ci.sharingMode = swapchain_node->createInfo.imageSharingMode; 106111facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis dev_data->imageMap[pSwapchainImages[i]] = unique_ptr<IMAGE_STATE>(new IMAGE_STATE(pSwapchainImages[i], &image_ci)); 106121facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis auto &image_state = dev_data->imageMap[pSwapchainImages[i]]; 106131facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis image_state->valid = false; 10614e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis image_state->binding.mem = MEMTRACKER_SWAP_CHAIN_IMAGE_KEY; 106155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis swapchain_node->images.push_back(pSwapchainImages[i]); 106165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis ImageSubresourcePair subpair = {pSwapchainImages[i], false, VkImageSubresource()}; 106175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->imageSubresourceMap[pSwapchainImages[i]].push_back(subpair); 106185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->imageLayoutMap[subpair] = image_layout_node; 106195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->device_extensions.imageToSwapchainMap[pSwapchainImages[i]] = swapchain; 106205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 106215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 106225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 106235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 106245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1062589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo) { 1062656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map); 106275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool skip_call = false; 106285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 106296c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes std::lock_guard<std::mutex> lock(global_lock); 106309a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto queue_state = GetQueueState(dev_data, queue); 106311671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes 106326c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes for (uint32_t i = 0; i < pPresentInfo->waitSemaphoreCount; ++i) { 106339a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pSemaphore = GetSemaphoreNode(dev_data, pPresentInfo->pWaitSemaphores[i]); 106346c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes if (pSemaphore && !pSemaphore->signaled) { 10635226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 10636226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, 10637226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "DS", "Queue 0x%p is waiting on semaphore 0x%" PRIx64 " that has no way to be signaled.", queue, 10638226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis reinterpret_cast<const uint64_t &>(pPresentInfo->pWaitSemaphores[i])); 106395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 106406c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes } 10641249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis 106426c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes for (uint32_t i = 0; i < pPresentInfo->swapchainCount; ++i) { 106439a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto swapchain_data = GetSwapchainNode(dev_data, pPresentInfo->pSwapchains[i]); 10644a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes if (swapchain_data) { 10645a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes if (pPresentInfo->pImageIndices[i] >= swapchain_data->images.size()) { 10646bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski skip_call |= log_msg( 10647bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 10648bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski reinterpret_cast<uint64_t const &>(pPresentInfo->pSwapchains[i]), __LINE__, DRAWSTATE_SWAPCHAIN_INVALID_IMAGE, 10649bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "DS", "vkQueuePresentKHR: Swapchain image index too large (%u). There are only %u images in this swapchain.", 10650bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pPresentInfo->pImageIndices[i], (uint32_t)swapchain_data->images.size()); 10651bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski } else { 10652a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes auto image = swapchain_data->images[pPresentInfo->pImageIndices[i]]; 106539a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_state = GetImageState(dev_data, image); 106541facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis skip_call |= ValidateImageMemoryIsValid(dev_data, image_state, "vkQueuePresentKHR()"); 10655a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes 106561facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis if (!image_state->acquired) { 10657bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski skip_call |= log_msg( 10658bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 10659bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski reinterpret_cast<uint64_t const &>(pPresentInfo->pSwapchains[i]), __LINE__, 10660bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski DRAWSTATE_SWAPCHAIN_IMAGE_NOT_ACQUIRED, "DS", 10661bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "vkQueuePresentKHR: Swapchain image index %u has not been acquired.", pPresentInfo->pImageIndices[i]); 10662a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes } 10663a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes 10664a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes vector<VkImageLayout> layouts; 10665a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes if (FindLayouts(dev_data, image, layouts)) { 10666a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes for (auto layout : layouts) { 10667a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes if (layout != VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) { 10668a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes skip_call |= 106692fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT, 106702fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t &>(queue), __LINE__, VALIDATION_ERROR_01964, "DS", 106712fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen "Images passed to present must be in layout " 106722fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen "VK_IMAGE_LAYOUT_PRESENT_SRC_KHR but is in %s. %s", 106732fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen string_VkImageLayout(layout), validation_error_map[VALIDATION_ERROR_01964]); 10674a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes } 106755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 106765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 106775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 106781671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes 106791671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes // All physical devices and queue families are required to be able 106801671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes // to present to any native window on Android; require the 106811671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes // application to have established support on any other platform. 106821671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes if (!dev_data->instance_data->androidSurfaceExtensionEnabled) { 106839a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto surface_state = GetSurfaceState(dev_data->instance_data, swapchain_data->createInfo.surface); 106841671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes auto support_it = surface_state->gpu_queue_support.find({dev_data->physical_device, queue_state->queueFamilyIndex}); 106851671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes 106861671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes if (support_it == surface_state->gpu_queue_support.end()) { 106871671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes skip_call |= 106881671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 106891671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes reinterpret_cast<uint64_t const &>(pPresentInfo->pSwapchains[i]), __LINE__, 10690cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski DRAWSTATE_SWAPCHAIN_UNSUPPORTED_QUEUE, "DS", 10691cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkQueuePresentKHR: Presenting image without calling " 10692cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkGetPhysicalDeviceSurfaceSupportKHR"); 106931671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes } else if (!support_it->second) { 10694cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski skip_call |= log_msg( 10695cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 10696cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski reinterpret_cast<uint64_t const &>(pPresentInfo->pSwapchains[i]), __LINE__, VALIDATION_ERROR_01961, "DS", 10697cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkQueuePresentKHR: Presenting image on queue that cannot " 10698cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "present to this surface. %s", 10699cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski validation_error_map[VALIDATION_ERROR_01961]); 107001671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes } 107011671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes } 107025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 107035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 107045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 107056c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes if (skip_call) { 107066c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes return VK_ERROR_VALIDATION_FAILED_EXT; 107076c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes } 107086c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes 107094a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.QueuePresentKHR(queue, pPresentInfo); 107106c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes 107116c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes if (result != VK_ERROR_VALIDATION_FAILED_EXT) { 107126c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes // Semaphore waits occur before error generation, if the call reached 107136c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes // the ICD. (Confirm?) 107146c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes for (uint32_t i = 0; i < pPresentInfo->waitSemaphoreCount; ++i) { 107159a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pSemaphore = GetSemaphoreNode(dev_data, pPresentInfo->pWaitSemaphores[i]); 107169867daedbf52debc77d6568162ee21e071699b80Chris Forbes if (pSemaphore) { 107179867daedbf52debc77d6568162ee21e071699b80Chris Forbes pSemaphore->signaler.first = VK_NULL_HANDLE; 107186c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes pSemaphore->signaled = false; 107196c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes } 107206c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes } 107219867daedbf52debc77d6568162ee21e071699b80Chris Forbes 10722220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes for (uint32_t i = 0; i < pPresentInfo->swapchainCount; ++i) { 10723220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes // Note: this is imperfect, in that we can get confused about what 10724220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes // did or didn't succeed-- but if the app does that, it's confused 10725220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes // itself just as much. 10726220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes auto local_result = pPresentInfo->pResults ? pPresentInfo->pResults[i] : result; 10727220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes 10728cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (local_result != VK_SUCCESS && local_result != VK_SUBOPTIMAL_KHR) continue; // this present didn't actually happen. 10729220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes 10730220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes // Mark the image as having been released to the WSI 107319a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto swapchain_data = GetSwapchainNode(dev_data, pPresentInfo->pSwapchains[i]); 10732220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes auto image = swapchain_data->images[pPresentInfo->pImageIndices[i]]; 107339a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_state = GetImageState(dev_data, image); 107341facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis image_state->acquired = false; 10735220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes } 10736220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes 107379867daedbf52debc77d6568162ee21e071699b80Chris Forbes // Note: even though presentation is directed to a queue, there is no 107389867daedbf52debc77d6568162ee21e071699b80Chris Forbes // direct ordering between QP and subsequent work, so QP (and its 107399867daedbf52debc77d6568162ee21e071699b80Chris Forbes // semaphore waits) /never/ participate in any completion proof. 107406c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes } 107411344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis 107425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 107435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 107445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10745c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinskistatic bool PreCallValidateCreateSharedSwapchainsKHR(layer_data *dev_data, uint32_t swapchainCount, 10746c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski const VkSwapchainCreateInfoKHR *pCreateInfos, VkSwapchainKHR *pSwapchains, 10747c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski std::vector<SURFACE_STATE *> &surface_state, 10748c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski std::vector<SWAPCHAIN_NODE *> &old_swapchain_state) { 107490342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski if (pCreateInfos) { 10750c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski std::lock_guard<std::mutex> lock(global_lock); 107510342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski for (uint32_t i = 0; i < swapchainCount; i++) { 107529a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis surface_state.push_back(GetSurfaceState(dev_data->instance_data, pCreateInfos[i].surface)); 107539a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis old_swapchain_state.push_back(GetSwapchainNode(dev_data, pCreateInfos[i].oldSwapchain)); 107549ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski std::stringstream func_name; 107559ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski func_name << "vkCreateSharedSwapchainsKHR[" << swapchainCount << "]"; 10756bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (PreCallValidateCreateSwapchainKHR(dev_data, func_name.str().c_str(), &pCreateInfos[i], surface_state[i], 10757bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski old_swapchain_state[i])) { 10758c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski return true; 107590342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski } 107600342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski } 107610342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski } 10762c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski return false; 10763c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski} 107640342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski 10765c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinskistatic void PostCallRecordCreateSharedSwapchainsKHR(layer_data *dev_data, VkResult result, uint32_t swapchainCount, 10766c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski const VkSwapchainCreateInfoKHR *pCreateInfos, VkSwapchainKHR *pSwapchains, 10767c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski std::vector<SURFACE_STATE *> &surface_state, 10768c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski std::vector<SWAPCHAIN_NODE *> &old_swapchain_state) { 107690342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski if (VK_SUCCESS == result) { 107700342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski for (uint32_t i = 0; i < swapchainCount; i++) { 107710342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski auto swapchain_state = unique_ptr<SWAPCHAIN_NODE>(new SWAPCHAIN_NODE(&pCreateInfos[i], pSwapchains[i])); 107720342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski surface_state[i]->swapchain = swapchain_state.get(); 107730342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski dev_data->device_extensions.swapchainMap[pSwapchains[i]] = std::move(swapchain_state); 107740342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski } 107750342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski } else { 107760342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski for (uint32_t i = 0; i < swapchainCount; i++) { 107770342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski surface_state[i]->swapchain = nullptr; 107780342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski } 107790342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski } 107800342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski // Spec requires that even if CreateSharedSwapchainKHR fails, oldSwapchain behaves as replaced. 107810342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski for (uint32_t i = 0; i < swapchainCount; i++) { 107820342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski if (old_swapchain_state[i]) { 107830342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski old_swapchain_state[i]->replaced = true; 107840342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski } 107850342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski surface_state[i]->old_swapchain = old_swapchain_state[i]; 107860342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski } 10787c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski return; 10788c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski} 10789c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski 10790c6cd632d064579a64e61d8704b411d0e4ace7adaMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateSharedSwapchainsKHR(VkDevice device, uint32_t swapchainCount, 10791c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski const VkSwapchainCreateInfoKHR *pCreateInfos, 10792c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchains) { 1079356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 10794c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski std::vector<SURFACE_STATE *> surface_state; 10795c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski std::vector<SWAPCHAIN_NODE *> old_swapchain_state; 10796c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski 10797c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski if (PreCallValidateCreateSharedSwapchainsKHR(dev_data, swapchainCount, pCreateInfos, pSwapchains, surface_state, 10798c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski old_swapchain_state)) { 10799c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski return VK_ERROR_VALIDATION_FAILED_EXT; 10800c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski } 10801c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski 10802c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski VkResult result = 10803c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski dev_data->dispatch_table.CreateSharedSwapchainsKHR(device, swapchainCount, pCreateInfos, pAllocator, pSwapchains); 10804c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski 10805c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski PostCallRecordCreateSharedSwapchainsKHR(dev_data, result, swapchainCount, pCreateInfos, pSwapchains, surface_state, 10806c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski old_swapchain_state); 108070342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski 10808c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young return result; 10809c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young} 10810c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young 1081189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL AcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, 1081289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu VkSemaphore semaphore, VkFence fence, uint32_t *pImageIndex) { 1081356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 1081483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 108151344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis 10816b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 10817449670637ef4214b33018f497cf10daeff9dc85bChris Forbes 10818449670637ef4214b33018f497cf10daeff9dc85bChris Forbes if (fence == VK_NULL_HANDLE && semaphore == VK_NULL_HANDLE) { 10819449670637ef4214b33018f497cf10daeff9dc85bChris Forbes skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 10820d17d86d15a733f1ec988956721ea4b7cdfb6771bChris Forbes reinterpret_cast<uint64_t &>(device), __LINE__, DRAWSTATE_SWAPCHAIN_NO_SYNC_FOR_ACQUIRE, "DS", 10821449670637ef4214b33018f497cf10daeff9dc85bChris Forbes "vkAcquireNextImageKHR: Semaphore and fence cannot both be VK_NULL_HANDLE. There would be no way " 10822449670637ef4214b33018f497cf10daeff9dc85bChris Forbes "to determine the completion of this operation."); 10823449670637ef4214b33018f497cf10daeff9dc85bChris Forbes } 10824449670637ef4214b33018f497cf10daeff9dc85bChris Forbes 108259a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pSemaphore = GetSemaphoreNode(dev_data, semaphore); 10826f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes if (pSemaphore && pSemaphore->signaled) { 1082783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT, 108282fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<const uint64_t &>(semaphore), __LINE__, VALIDATION_ERROR_01952, "DS", 108292fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen "vkAcquireNextImageKHR: Semaphore must not be currently signaled or in a wait state. %s", 108302fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen validation_error_map[VALIDATION_ERROR_01952]); 108315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 10832f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes 108339a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pFence = GetFenceNode(dev_data, fence); 10834f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes if (pFence) { 1083583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= ValidateFenceForSubmit(dev_data, pFence); 108365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 108374a5614452104c88cb04390dac882dd94ebdcc3deChris Forbes 108389a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto swapchain_data = GetSwapchainNode(dev_data, swapchain); 10839fc9f0448c3cb6ba4fc018fefe761bb43a1884846Chris Forbes 10840fc9f0448c3cb6ba4fc018fefe761bb43a1884846Chris Forbes if (swapchain_data->replaced) { 10841fc9f0448c3cb6ba4fc018fefe761bb43a1884846Chris Forbes skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 10842fc9f0448c3cb6ba4fc018fefe761bb43a1884846Chris Forbes reinterpret_cast<uint64_t &>(swapchain), __LINE__, DRAWSTATE_SWAPCHAIN_REPLACED, "DS", 10843fc9f0448c3cb6ba4fc018fefe761bb43a1884846Chris Forbes "vkAcquireNextImageKHR: This swapchain has been replaced. The application can still " 10844fc9f0448c3cb6ba4fc018fefe761bb43a1884846Chris Forbes "present any images it has acquired, but cannot acquire any more."); 10845fc9f0448c3cb6ba4fc018fefe761bb43a1884846Chris Forbes } 10846fc9f0448c3cb6ba4fc018fefe761bb43a1884846Chris Forbes 108479a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto physical_device_state = GetPhysicalDeviceState(dev_data->instance_data, dev_data->physical_device); 108484a5614452104c88cb04390dac882dd94ebdcc3deChris Forbes if (physical_device_state->vkGetPhysicalDeviceSurfaceCapabilitiesKHRState != UNCALLED) { 108496569ab421f45f905e69fa7345bda4fe5b87e9045Mark Lobodzinski uint64_t acquired_images = std::count_if(swapchain_data->images.begin(), swapchain_data->images.end(), 108509a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis [=](VkImage image) { return GetImageState(dev_data, image)->acquired; }); 108514a5614452104c88cb04390dac882dd94ebdcc3deChris Forbes if (acquired_images > swapchain_data->images.size() - physical_device_state->surfaceCapabilities.minImageCount) { 108526569ab421f45f905e69fa7345bda4fe5b87e9045Mark Lobodzinski skip_call |= 108536569ab421f45f905e69fa7345bda4fe5b87e9045Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 108546569ab421f45f905e69fa7345bda4fe5b87e9045Mark Lobodzinski reinterpret_cast<uint64_t const &>(swapchain), __LINE__, DRAWSTATE_SWAPCHAIN_TOO_MANY_IMAGES, "DS", 108556569ab421f45f905e69fa7345bda4fe5b87e9045Mark Lobodzinski "vkAcquireNextImageKHR: Application has already acquired the maximum number of images (0x%" PRIxLEAST64 ")", 108566569ab421f45f905e69fa7345bda4fe5b87e9045Mark Lobodzinski acquired_images); 108574a5614452104c88cb04390dac882dd94ebdcc3deChris Forbes } 108584a5614452104c88cb04390dac882dd94ebdcc3deChris Forbes } 1085975269fc9e5cc9696ddf3dd28ff201c9b2526dc7aThomas Louis 1086075269fc9e5cc9696ddf3dd28ff201c9b2526dc7aThomas Louis if (swapchain_data->images.size() == 0) { 1086175269fc9e5cc9696ddf3dd28ff201c9b2526dc7aThomas Louis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 1086275269fc9e5cc9696ddf3dd28ff201c9b2526dc7aThomas Louis reinterpret_cast<uint64_t const &>(swapchain), __LINE__, DRAWSTATE_SWAPCHAIN_IMAGES_NOT_FOUND, "DS", 1086375269fc9e5cc9696ddf3dd28ff201c9b2526dc7aThomas Louis "vkAcquireNextImageKHR: No images found to acquire from. Application probably did not call " 1086475269fc9e5cc9696ddf3dd28ff201c9b2526dc7aThomas Louis "vkGetSwapchainImagesKHR after swapchain creation."); 1086575269fc9e5cc9696ddf3dd28ff201c9b2526dc7aThomas Louis } 1086675269fc9e5cc9696ddf3dd28ff201c9b2526dc7aThomas Louis 10867b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 108681344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis 10869cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip_call) return VK_ERROR_VALIDATION_FAILED_EXT; 10870f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes 108714a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.AcquireNextImageKHR(device, swapchain, timeout, semaphore, fence, pImageIndex); 10872f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes 10873f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes lock.lock(); 10874f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes if (result == VK_SUCCESS || result == VK_SUBOPTIMAL_KHR) { 10875f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes if (pFence) { 10876f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes pFence->state = FENCE_INFLIGHT; 10877cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pFence->signaler.first = VK_NULL_HANDLE; // ANI isn't on a queue, so this can't participate in a completion proof. 10878f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes } 10879f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes 10880f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes // A successful call to AcquireNextImageKHR counts as a signal operation on semaphore 10881f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes if (pSemaphore) { 10882f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes pSemaphore->signaled = true; 108839867daedbf52debc77d6568162ee21e071699b80Chris Forbes pSemaphore->signaler.first = VK_NULL_HANDLE; 10884f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes } 10885220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes 10886220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes // Mark the image as acquired. 10887220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes auto image = swapchain_data->images[*pImageIndex]; 108889a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_state = GetImageState(dev_data, image); 108891facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis image_state->acquired = true; 108905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 10891f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes lock.unlock(); 108921344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis 108935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 108945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 108955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10896f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL EnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount, 10897f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski VkPhysicalDevice *pPhysicalDevices) { 1089883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 1089956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 10900bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis assert(instance_data); 10901219f00ffed576643641976122fa1db8e5fce5dc1Chris Forbes 10902bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis // For this instance, flag when vkEnumeratePhysicalDevices goes to QUERY_COUNT and then QUERY_DETAILS 10903bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis if (NULL == pPhysicalDevices) { 10904bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis instance_data->vkEnumeratePhysicalDevicesState = QUERY_COUNT; 10905f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski } else { 10906bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis if (UNCALLED == instance_data->vkEnumeratePhysicalDevicesState) { 10907bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis // Flag warning here. You can call this without having queried the count, but it may not be 10908bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis // robust on platforms with multiple physical devices. 10909bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis skip_call |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, 10910bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, 0, __LINE__, DEVLIMITS_MISSING_QUERY_COUNT, "DL", 10911bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis "Call sequence has vkEnumeratePhysicalDevices() w/ non-NULL pPhysicalDevices. You should first " 10912bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis "call vkEnumeratePhysicalDevices() w/ NULL pPhysicalDevices to query pPhysicalDeviceCount."); 10913cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } // TODO : Could also flag a warning if re-calling this function in QUERY_DETAILS state 10914bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis else if (instance_data->physical_devices_count != *pPhysicalDeviceCount) { 10915bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis // Having actual count match count from app is not a requirement, so this can be a warning 10916bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis skip_call |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, 10917bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_COUNT_MISMATCH, "DL", 10918bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis "Call to vkEnumeratePhysicalDevices() w/ pPhysicalDeviceCount value %u, but actual count " 10919bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis "supported by this instance is %u.", 10920bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis *pPhysicalDeviceCount, instance_data->physical_devices_count); 10921bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis } 10922bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis instance_data->vkEnumeratePhysicalDevicesState = QUERY_DETAILS; 10923f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski } 10924bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis if (skip_call) { 10925bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis return VK_ERROR_VALIDATION_FAILED_EXT; 10926bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis } 10927bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis VkResult result = instance_data->dispatch_table.EnumeratePhysicalDevices(instance, pPhysicalDeviceCount, pPhysicalDevices); 10928bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis if (NULL == pPhysicalDevices) { 10929bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis instance_data->physical_devices_count = *pPhysicalDeviceCount; 10930cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else if (result == VK_SUCCESS) { // Save physical devices 10931bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++) { 10932bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis auto &phys_device_state = instance_data->physical_device_map[pPhysicalDevices[i]]; 10933bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis phys_device_state.phys_device = pPhysicalDevices[i]; 10934bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis // Init actual features for each physical device 10935bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis instance_data->dispatch_table.GetPhysicalDeviceFeatures(pPhysicalDevices[i], &phys_device_state.features); 10936bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis } 10937bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis } 10938bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis return result; 10939f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski} 10940f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski 1094143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis// Common function to handle validation for GetPhysicalDeviceQueueFamilyProperties & 2KHR version 1094243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic bool ValidateCommonGetPhysicalDeviceQueueFamilyProperties(instance_layer_data *instance_data, 1094343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis PHYSICAL_DEVICE_STATE *pd_state, 1094443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis uint32_t *pQueueFamilyPropertyCount, bool qfp_null, 1094543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis const char *count_var_name, const char *caller_name) { 1094643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis bool skip = false; 1094743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis if (qfp_null) { 1094843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis pd_state->vkGetPhysicalDeviceQueueFamilyPropertiesState = QUERY_COUNT; 1094943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } else { 1095043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis // Verify that for each physical device, this function is called first with NULL pQueueFamilyProperties ptr in order to get 1095143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis // count 1095243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis if (UNCALLED == pd_state->vkGetPhysicalDeviceQueueFamilyPropertiesState) { 1095343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, 1095443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_MISSING_QUERY_COUNT, "DL", 1095543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis "Call sequence has %s() w/ non-NULL " 1095643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis "pQueueFamilyProperties. You should first call %s() w/ " 1095743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis "NULL pQueueFamilyProperties to query pCount.", 1095843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis caller_name, caller_name); 1095943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 1096043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis // Then verify that pCount that is passed in on second call matches what was returned 1096143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis if (pd_state->queueFamilyPropertiesCount != *pQueueFamilyPropertyCount) { 1096243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis // TODO: this is not a requirement of the Valid Usage section for vkGetPhysicalDeviceQueueFamilyProperties, so 1096343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis // provide as warning 1096443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, 1096543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_COUNT_MISMATCH, "DL", 1096643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis "Call to %s() w/ %s value %u, but actual count supported by this physicalDevice is %u.", caller_name, 1096743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis count_var_name, *pQueueFamilyPropertyCount, pd_state->queueFamilyPropertiesCount); 1096843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 1096943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis pd_state->vkGetPhysicalDeviceQueueFamilyPropertiesState = QUERY_DETAILS; 1097043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 1097143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis return skip; 1097243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis} 1097343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis 1097443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic bool PreCallValidateGetPhysicalDeviceQueueFamilyProperties(instance_layer_data *instance_data, 1097543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis PHYSICAL_DEVICE_STATE *pd_state, uint32_t *pCount, 1097643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis VkQueueFamilyProperties *pQueueFamilyProperties) { 1097743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis return ValidateCommonGetPhysicalDeviceQueueFamilyProperties(instance_data, pd_state, pCount, 1097843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis (nullptr == pQueueFamilyProperties), "pCount", 1097943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis "vkGetPhysicalDeviceQueueFamilyProperties()"); 1098043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis} 1098143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis 1098243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic bool PreCallValidateGetPhysicalDeviceQueueFamilyProperties2KHR(instance_layer_data *instance_data, 1098343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis PHYSICAL_DEVICE_STATE *pd_state, 1098443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis uint32_t *pQueueFamilyPropertyCount, 1098543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis VkQueueFamilyProperties2KHR *pQueueFamilyProperties) { 1098643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis return ValidateCommonGetPhysicalDeviceQueueFamilyProperties(instance_data, pd_state, pQueueFamilyPropertyCount, 1098743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis (nullptr == pQueueFamilyProperties), "pQueueFamilyPropertyCount", 1098843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis "vkGetPhysicalDeviceQueueFamilyProperties2KHR()"); 1098943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis} 1099043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis 1099143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis// Common function to update state for GetPhysicalDeviceQueueFamilyProperties & 2KHR version 1099243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic void StateUpdateCommonGetPhysicalDeviceQueueFamilyProperties(PHYSICAL_DEVICE_STATE *pd_state, uint32_t count, 1099343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis VkQueueFamilyProperties2KHR *pQueueFamilyProperties) { 1099443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis if (!pQueueFamilyProperties) { 1099543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis pd_state->queueFamilyPropertiesCount = count; 1099643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } else { // Save queue family properties 1099743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis if (pd_state->queue_family_properties.size() < count) pd_state->queue_family_properties.resize(count); 1099843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis for (uint32_t i = 0; i < count; i++) { 1099943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis pd_state->queue_family_properties[i] = pQueueFamilyProperties[i].queueFamilyProperties; 1100043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 1100143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 1100243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis} 1100343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis 1100443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic void PostCallRecordGetPhysicalDeviceQueueFamilyProperties(PHYSICAL_DEVICE_STATE *pd_state, uint32_t count, 1100543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis VkQueueFamilyProperties *pQueueFamilyProperties) { 1100643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis VkQueueFamilyProperties2KHR *pqfp = nullptr; 1100743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis std::vector<VkQueueFamilyProperties2KHR> qfp; 1100843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis qfp.resize(count); 1100943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis if (pQueueFamilyProperties) { 1101043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis for (uint32_t i = 0; i < count; ++i) { 1101143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis qfp[i].sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2_KHR; 1101243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis qfp[i].pNext = nullptr; 1101343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis qfp[i].queueFamilyProperties = pQueueFamilyProperties[i]; 1101443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 1101543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis pqfp = qfp.data(); 1101643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 1101743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis StateUpdateCommonGetPhysicalDeviceQueueFamilyProperties(pd_state, count, pqfp); 1101843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis} 1101943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis 1102043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic void PostCallRecordGetPhysicalDeviceQueueFamilyProperties2KHR(PHYSICAL_DEVICE_STATE *pd_state, uint32_t count, 1102143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis VkQueueFamilyProperties2KHR *pQueueFamilyProperties) { 1102243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis StateUpdateCommonGetPhysicalDeviceQueueFamilyProperties(pd_state, count, pQueueFamilyProperties); 1102343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis} 1102443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis 11025bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, 11026bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkQueueFamilyProperties *pQueueFamilyProperties) { 1102756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 110289a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto physical_device_state = GetPhysicalDeviceState(instance_data, physicalDevice); 1102943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis assert(physical_device_state); 1103043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis bool skip = 1103143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis PreCallValidateGetPhysicalDeviceQueueFamilyProperties(instance_data, physical_device_state, pCount, pQueueFamilyProperties); 1103243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis if (skip) { 1103343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis return; 1103443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 1103543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis instance_data->dispatch_table.GetPhysicalDeviceQueueFamilyProperties(physicalDevice, pCount, pQueueFamilyProperties); 1103643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis PostCallRecordGetPhysicalDeviceQueueFamilyProperties(physical_device_state, *pCount, pQueueFamilyProperties); 1103743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis} 1103843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis 1103943947a6175e3e942e04d902f4d18928168e2d0dbTobin EhlisVKAPI_ATTR void VKAPI_CALL GetPhysicalDeviceQueueFamilyProperties2KHR(VkPhysicalDevice physicalDevice, 1104043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis uint32_t *pQueueFamilyPropertyCount, 1104143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis VkQueueFamilyProperties2KHR *pQueueFamilyProperties) { 1104256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 110439a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto physical_device_state = GetPhysicalDeviceState(instance_data, physicalDevice); 1104443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis assert(physical_device_state); 1104543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis bool skip = PreCallValidateGetPhysicalDeviceQueueFamilyProperties2KHR(instance_data, physical_device_state, 1104643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis pQueueFamilyPropertyCount, pQueueFamilyProperties); 1104743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis if (skip) { 1104843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis return; 11049cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski } 1105043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis instance_data->dispatch_table.GetPhysicalDeviceQueueFamilyProperties2KHR(physicalDevice, pQueueFamilyPropertyCount, 1105143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis pQueueFamilyProperties); 1105243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis PostCallRecordGetPhysicalDeviceQueueFamilyProperties2KHR(physical_device_state, *pQueueFamilyPropertyCount, 1105343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis pQueueFamilyProperties); 11054cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski} 11055cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski 11056bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskitemplate <typename TCreateInfo, typename FPtr> 11057bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic VkResult CreateSurface(VkInstance instance, TCreateInfo const *pCreateInfo, VkAllocationCallbacks const *pAllocator, 11058bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkSurfaceKHR *pSurface, FPtr fptr) { 1105956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 11060747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11061747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes // Call down the call chain: 11062747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes VkResult result = (instance_data->dispatch_table.*fptr)(instance, pCreateInfo, pAllocator, pSurface); 11063747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11064747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (result == VK_SUCCESS) { 11065747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes std::unique_lock<std::mutex> lock(global_lock); 11066747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->surface_map[*pSurface] = SURFACE_STATE(*pSurface); 11067747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes lock.unlock(); 11068747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes } 11069747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11070747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes return result; 11071747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 11072747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11073747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR void VKAPI_CALL DestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks *pAllocator) { 11074747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes bool skip_call = false; 1107556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 11076747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes std::unique_lock<std::mutex> lock(global_lock); 110779a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto surface_state = GetSurfaceState(instance_data, surface); 11078747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11079747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (surface_state) { 11080747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes // TODO: track swapchains created from this surface. 11081747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->surface_map.erase(surface); 11082747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes } 11083747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes lock.unlock(); 11084747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11085747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (!skip_call) { 11086747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes // Call down the call chain: 11087747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->dispatch_table.DestroySurfaceKHR(instance, surface, pAllocator); 11088747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes } 11089747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 11090747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 110916f2ed666809272002a31b3b4f8adf6581cb41819Norbert NopperVKAPI_ATTR VkResult VKAPI_CALL CreateDisplayPlaneSurfaceKHR(VkInstance instance, const VkDisplaySurfaceCreateInfoKHR *pCreateInfo, 110926f2ed666809272002a31b3b4f8adf6581cb41819Norbert Nopper const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) { 110936f2ed666809272002a31b3b4f8adf6581cb41819Norbert Nopper return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateDisplayPlaneSurfaceKHR); 110946f2ed666809272002a31b3b4f8adf6581cb41819Norbert Nopper} 110956f2ed666809272002a31b3b4f8adf6581cb41819Norbert Nopper 11096747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_ANDROID_KHR 11097747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR *pCreateInfo, 11098747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) { 11099747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateAndroidSurfaceKHR); 11100747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 11101cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_ANDROID_KHR 11102747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11103747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_MIR_KHR 11104747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateMirSurfaceKHR(VkInstance instance, const VkMirSurfaceCreateInfoKHR *pCreateInfo, 11105747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) { 11106747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateMirSurfaceKHR); 11107747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 11108cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_MIR_KHR 11109747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11110747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_WAYLAND_KHR 11111747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateWaylandSurfaceKHR(VkInstance instance, const VkWaylandSurfaceCreateInfoKHR *pCreateInfo, 11112747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) { 11113a9c6cc532ce0ef61d48d1419a96aae51b0e4c64aTobin Ehlis return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateWaylandSurfaceKHR); 11114747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 11115cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_WAYLAND_KHR 11116747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11117747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_WIN32_KHR 11118747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateWin32SurfaceKHR(VkInstance instance, const VkWin32SurfaceCreateInfoKHR *pCreateInfo, 11119747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) { 11120747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateWin32SurfaceKHR); 11121747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 11122cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_WIN32_KHR 11123747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11124747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_XCB_KHR 11125747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateXcbSurfaceKHR(VkInstance instance, const VkXcbSurfaceCreateInfoKHR *pCreateInfo, 11126747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) { 11127747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateXcbSurfaceKHR); 11128747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 11129cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_XCB_KHR 11130747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11131747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_XLIB_KHR 11132747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateXlibSurfaceKHR(VkInstance instance, const VkXlibSurfaceCreateInfoKHR *pCreateInfo, 11133bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) { 11134747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateXlibSurfaceKHR); 11135747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 11136cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_XLIB_KHR 11137747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 1113840921785005eb449ec7c18229f0d84c879708b8aChris ForbesVKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, 1113940921785005eb449ec7c18229f0d84c879708b8aChris Forbes VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) { 1114056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis auto instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 1114140921785005eb449ec7c18229f0d84c879708b8aChris Forbes 1114240921785005eb449ec7c18229f0d84c879708b8aChris Forbes std::unique_lock<std::mutex> lock(global_lock); 111439a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto physical_device_state = GetPhysicalDeviceState(instance_data, physicalDevice); 1114440921785005eb449ec7c18229f0d84c879708b8aChris Forbes lock.unlock(); 1114540921785005eb449ec7c18229f0d84c879708b8aChris Forbes 11146bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto result = 11147bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski instance_data->dispatch_table.GetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, pSurfaceCapabilities); 1114840921785005eb449ec7c18229f0d84c879708b8aChris Forbes 1114940921785005eb449ec7c18229f0d84c879708b8aChris Forbes if (result == VK_SUCCESS) { 1115040921785005eb449ec7c18229f0d84c879708b8aChris Forbes physical_device_state->vkGetPhysicalDeviceSurfaceCapabilitiesKHRState = QUERY_DETAILS; 1115140921785005eb449ec7c18229f0d84c879708b8aChris Forbes physical_device_state->surfaceCapabilities = *pSurfaceCapabilities; 1115240921785005eb449ec7c18229f0d84c879708b8aChris Forbes } 1115340921785005eb449ec7c18229f0d84c879708b8aChris Forbes 1115440921785005eb449ec7c18229f0d84c879708b8aChris Forbes return result; 1115540921785005eb449ec7c18229f0d84c879708b8aChris Forbes} 1115640921785005eb449ec7c18229f0d84c879708b8aChris Forbes 11157418a8711f3301f3027a900bb45daaf0892f4e644Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, 11158418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes VkSurfaceKHR surface, VkBool32 *pSupported) { 1115956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis auto instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 11160418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes std::unique_lock<std::mutex> lock(global_lock); 111619a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto surface_state = GetSurfaceState(instance_data, surface); 11162418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes lock.unlock(); 11163418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes 11164bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto result = 11165bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski instance_data->dispatch_table.GetPhysicalDeviceSurfaceSupportKHR(physicalDevice, queueFamilyIndex, surface, pSupported); 11166418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes 11167418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes if (result == VK_SUCCESS) { 111686569ab421f45f905e69fa7345bda4fe5b87e9045Mark Lobodzinski surface_state->gpu_queue_support[{physicalDevice, queueFamilyIndex}] = (*pSupported != 0); 11169418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes } 11170418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes 11171418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes return result; 11172418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes} 11173418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes 111749e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, 111759e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes uint32_t *pPresentModeCount, 111769e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes VkPresentModeKHR *pPresentModes) { 111779e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes bool skip_call = false; 1117856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis auto instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 111799e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes std::unique_lock<std::mutex> lock(global_lock); 111809e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes // TODO: this isn't quite right. available modes may differ by surface AND physical device. 111819a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto physical_device_state = GetPhysicalDeviceState(instance_data, physicalDevice); 11182bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto &call_state = physical_device_state->vkGetPhysicalDeviceSurfacePresentModesKHRState; 111839e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes 111849e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (pPresentModes) { 111859e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes // Compare the preliminary value of *pPresentModeCount with the value this time: 11186bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto prev_mode_count = (uint32_t)physical_device_state->present_modes.size(); 111879e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes switch (call_state) { 11188cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case UNCALLED: 111899e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes skip_call |= log_msg( 11190bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 11191cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski reinterpret_cast<uint64_t>(physicalDevice), __LINE__, DEVLIMITS_MUST_QUERY_COUNT, "DL", 11192cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkGetPhysicalDeviceSurfacePresentModesKHR() called with non-NULL pPresentModeCount; but no prior positive " 11193cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "value has been seen for pPresentModeCount."); 11194cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 11195cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 11196cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // both query count and query details 11197cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (*pPresentModeCount != prev_mode_count) { 11198cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski skip_call |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, 11199cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 11200cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski reinterpret_cast<uint64_t>(physicalDevice), __LINE__, DEVLIMITS_COUNT_MISMATCH, "DL", 11201cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkGetPhysicalDeviceSurfacePresentModesKHR() called with *pPresentModeCount (%u) that " 11202cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "differs from the value " 11203cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "(%u) that was returned when pPresentModes was NULL.", 11204cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski *pPresentModeCount, prev_mode_count); 11205cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 11206cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 112079e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 112089e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 112099e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes lock.unlock(); 112109e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes 11211cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip_call) return VK_ERROR_VALIDATION_FAILED_EXT; 112129e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes 11213bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto result = instance_data->dispatch_table.GetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, pPresentModeCount, 11214bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pPresentModes); 112159e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes 112169e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (result == VK_SUCCESS || result == VK_INCOMPLETE) { 112179e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes lock.lock(); 112189e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes 112199e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (*pPresentModeCount) { 11220cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (call_state < QUERY_COUNT) call_state = QUERY_COUNT; 112219e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (*pPresentModeCount > physical_device_state->present_modes.size()) 112229e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes physical_device_state->present_modes.resize(*pPresentModeCount); 112239e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 112249e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (pPresentModes) { 11225cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (call_state < QUERY_DETAILS) call_state = QUERY_DETAILS; 112269e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes for (uint32_t i = 0; i < *pPresentModeCount; i++) { 112279e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes physical_device_state->present_modes[i] = pPresentModes[i]; 112289e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 112299e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 112305faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 112315faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes 112325faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes return result; 112335faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes} 112345faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes 112355faa662f6859b01c72d79027abde363d5f10dcd7Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, 112365faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes uint32_t *pSurfaceFormatCount, 112375faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes VkSurfaceFormatKHR *pSurfaceFormats) { 112385faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes bool skip_call = false; 1123956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis auto instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 112405faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes std::unique_lock<std::mutex> lock(global_lock); 112419a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto physical_device_state = GetPhysicalDeviceState(instance_data, physicalDevice); 11242bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto &call_state = physical_device_state->vkGetPhysicalDeviceSurfaceFormatsKHRState; 112435faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes 112445faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (pSurfaceFormats) { 11245bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto prev_format_count = (uint32_t)physical_device_state->surface_formats.size(); 112465faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes 112475faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes switch (call_state) { 11248cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case UNCALLED: 11249cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Since we haven't recorded a preliminary value of *pSurfaceFormatCount, that likely means that the application 11250cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // didn't 11251cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // previously call this function with a NULL value of pSurfaceFormats: 112525faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes skip_call |= log_msg( 11253bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 11254cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski reinterpret_cast<uint64_t>(physicalDevice), __LINE__, DEVLIMITS_MUST_QUERY_COUNT, "DL", 11255cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkGetPhysicalDeviceSurfaceFormatsKHR() called with non-NULL pSurfaceFormatCount; but no prior positive " 11256cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "value has been seen for pSurfaceFormats."); 11257cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 11258cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 11259cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (prev_format_count != *pSurfaceFormatCount) { 11260cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski skip_call |= log_msg( 11261cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, 11262cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, reinterpret_cast<uint64_t>(physicalDevice), __LINE__, 11263cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski DEVLIMITS_COUNT_MISMATCH, "DL", 11264cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkGetPhysicalDeviceSurfaceFormatsKHR() called with non-NULL pSurfaceFormatCount, and with pSurfaceFormats " 11265cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "set " 11266cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "to " 11267cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "a value (%u) that is greater than the value (%u) that was returned when pSurfaceFormatCount was NULL.", 11268cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski *pSurfaceFormatCount, prev_format_count); 11269cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 11270cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 112719e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 112729e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 112735faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes lock.unlock(); 112745faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes 11275cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip_call) return VK_ERROR_VALIDATION_FAILED_EXT; 112769e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes 112775faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes // Call down the call chain: 112785faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes auto result = instance_data->dispatch_table.GetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, pSurfaceFormatCount, 112795faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes pSurfaceFormats); 112805faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes 112815faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (result == VK_SUCCESS || result == VK_INCOMPLETE) { 112825faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes lock.lock(); 112835faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes 112845faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (*pSurfaceFormatCount) { 11285cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (call_state < QUERY_COUNT) call_state = QUERY_COUNT; 112865faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (*pSurfaceFormatCount > physical_device_state->surface_formats.size()) 112875faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes physical_device_state->surface_formats.resize(*pSurfaceFormatCount); 112885faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 112895faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (pSurfaceFormats) { 11290cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (call_state < QUERY_DETAILS) call_state = QUERY_DETAILS; 112915faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes for (uint32_t i = 0; i < *pSurfaceFormatCount; i++) { 112925faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes physical_device_state->surface_formats[i] = pSurfaceFormats[i]; 112935faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 112945faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 112955faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 112969e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes return result; 112979e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes} 112989e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes 11299bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateDebugReportCallbackEXT(VkInstance instance, 11300bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkDebugReportCallbackCreateInfoEXT *pCreateInfo, 11301bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, 11302bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDebugReportCallbackEXT *pMsgCallback) { 1130356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 113049172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes VkResult res = instance_data->dispatch_table.CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback); 113055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == res) { 11306b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 113078860b85a52096f9f9b28616bc37feed505497a54Chris Forbes res = layer_create_msg_callback(instance_data->report_data, false, pCreateInfo, pAllocator, pMsgCallback); 113085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 113095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return res; 113105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 113115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 11312bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT msgCallback, 1131389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator) { 1131456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 113159172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes instance_data->dispatch_table.DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator); 11316b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 113178860b85a52096f9f9b28616bc37feed505497a54Chris Forbes layer_destroy_msg_callback(instance_data->report_data, msgCallback, pAllocator); 113185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 113195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 11320bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, 11321bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDebugReportObjectTypeEXT objType, uint64_t object, size_t location, 11322bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski int32_t msgCode, const char *pLayerPrefix, const char *pMsg) { 1132356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 113249172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes instance_data->dispatch_table.DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg); 113255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 113265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 11327bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) { 11328a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu return util_GetLayerProperties(1, &global_layer, pCount, pProperties); 11329a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu} 11330a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu 11331bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, 11332bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkLayerProperties *pProperties) { 11333a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu return util_GetLayerProperties(1, &global_layer, pCount, pProperties); 11334a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu} 11335a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu 11336bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, 11337bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkExtensionProperties *pProperties) { 11338a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) 11339a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties); 11340a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu 11341a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu return VK_ERROR_LAYER_NOT_PRESENT; 11342a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu} 11343a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu 11344bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName, 11345bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski uint32_t *pCount, VkExtensionProperties *pProperties) { 11346cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(0, NULL, pCount, pProperties); 11347a8f4a23b1e9c068717eda47cc583a93f447c77e3Chia-I Wu 11348a8f4a23b1e9c068717eda47cc583a93f447c77e3Chia-I Wu assert(physicalDevice); 11349a8f4a23b1e9c068717eda47cc583a93f447c77e3Chia-I Wu 1135056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 113519172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes return instance_data->dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties); 1135208939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu} 1135308939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu 11354bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic PFN_vkVoidFunction intercept_core_instance_command(const char *name); 113557ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu 11356bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic PFN_vkVoidFunction intercept_core_device_command(const char *name); 1135780be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu 11358bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic PFN_vkVoidFunction intercept_khr_swapchain_command(const char *name, VkDevice dev); 1135909a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu 11360bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic PFN_vkVoidFunction intercept_khr_surface_command(const char *name, VkInstance instance); 11361747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11362bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic PFN_vkVoidFunction intercept_extension_instance_commands(const char *name, VkInstance instance); 11363b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 1136489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice dev, const char *funcName) { 1136580be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu PFN_vkVoidFunction proc = intercept_core_device_command(funcName); 11366cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (proc) return proc; 1136780be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu 1136880be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu assert(dev); 113695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1137009a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu proc = intercept_khr_swapchain_command(funcName, dev); 11371cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (proc) return proc; 1137209a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu 1137356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(dev), layer_data_map); 113745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 113754a0754042cf090e131e9e769d8a3633c228625beChris Forbes auto &table = dev_data->dispatch_table; 11376cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!table.GetDeviceProcAddr) return nullptr; 113774a0754042cf090e131e9e769d8a3633c228625beChris Forbes return table.GetDeviceProcAddr(dev, funcName); 113785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 113795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1138089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) { 113817ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu PFN_vkVoidFunction proc = intercept_core_instance_command(funcName); 11382cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!proc) proc = intercept_core_device_command(funcName); 11383cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!proc) proc = intercept_khr_swapchain_command(funcName, VK_NULL_HANDLE); 11384cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!proc) proc = intercept_khr_surface_command(funcName, instance); 11385cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (proc) return proc; 113865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 113877ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu assert(instance); 113885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1138956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 113908860b85a52096f9f9b28616bc37feed505497a54Chris Forbes proc = debug_report_get_instance_proc_addr(instance_data->report_data, funcName); 11391cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (proc) return proc; 113925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 11393b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young proc = intercept_extension_instance_commands(funcName, instance); 11394cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (proc) return proc; 11395b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 113964a0754042cf090e131e9e769d8a3633c228625beChris Forbes auto &table = instance_data->dispatch_table; 11397cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!table.GetInstanceProcAddr) return nullptr; 113984a0754042cf090e131e9e769d8a3633c228625beChris Forbes return table.GetInstanceProcAddr(instance, funcName); 113995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 1140008939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu 11401b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark YoungVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetPhysicalDeviceProcAddr(VkInstance instance, const char *funcName) { 11402b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young assert(instance); 11403b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 1140456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 11405b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 11406b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young auto &table = instance_data->dispatch_table; 11407cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!table.GetPhysicalDeviceProcAddr) return nullptr; 11408b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young return table.GetPhysicalDeviceProcAddr(instance, funcName); 11409b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young} 11410b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 11411bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic PFN_vkVoidFunction intercept_core_instance_command(const char *name) { 114127ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu static const struct { 114137ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu const char *name; 114147ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu PFN_vkVoidFunction proc; 114157ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu } core_instance_commands[] = { 11416bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkGetInstanceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr)}, 11417bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vk_layerGetPhysicalDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceProcAddr)}, 11418bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkGetDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr)}, 11419bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkCreateInstance", reinterpret_cast<PFN_vkVoidFunction>(CreateInstance)}, 11420bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkCreateDevice", reinterpret_cast<PFN_vkVoidFunction>(CreateDevice)}, 11421bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkEnumeratePhysicalDevices", reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDevices)}, 11422bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkGetPhysicalDeviceQueueFamilyProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceQueueFamilyProperties)}, 11423bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance)}, 11424bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkEnumerateInstanceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceLayerProperties)}, 11425bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkEnumerateDeviceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceLayerProperties)}, 11426bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkEnumerateInstanceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceExtensionProperties)}, 11427bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkEnumerateDeviceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceExtensionProperties)}, 114287ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu }; 114297ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu 114307ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu for (size_t i = 0; i < ARRAY_SIZE(core_instance_commands); i++) { 11431cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!strcmp(core_instance_commands[i].name, name)) return core_instance_commands[i].proc; 114327ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu } 114337ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu 114347ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu return nullptr; 114357ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu} 114367ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu 11437bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic PFN_vkVoidFunction intercept_core_device_command(const char *name) { 1143880be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu static const struct { 1143980be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu const char *name; 1144080be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu PFN_vkVoidFunction proc; 1144180be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu } core_device_commands[] = { 11442593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkGetDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr)}, 11443593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkQueueSubmit", reinterpret_cast<PFN_vkVoidFunction>(QueueSubmit)}, 11444593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkWaitForFences", reinterpret_cast<PFN_vkVoidFunction>(WaitForFences)}, 11445593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkGetFenceStatus", reinterpret_cast<PFN_vkVoidFunction>(GetFenceStatus)}, 11446593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkQueueWaitIdle", reinterpret_cast<PFN_vkVoidFunction>(QueueWaitIdle)}, 11447593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDeviceWaitIdle", reinterpret_cast<PFN_vkVoidFunction>(DeviceWaitIdle)}, 11448593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkGetDeviceQueue", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceQueue)}, 11449593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance)}, 11450593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyDevice", reinterpret_cast<PFN_vkVoidFunction>(DestroyDevice)}, 11451593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyFence", reinterpret_cast<PFN_vkVoidFunction>(DestroyFence)}, 11452593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkResetFences", reinterpret_cast<PFN_vkVoidFunction>(ResetFences)}, 11453593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroySemaphore", reinterpret_cast<PFN_vkVoidFunction>(DestroySemaphore)}, 11454593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyEvent", reinterpret_cast<PFN_vkVoidFunction>(DestroyEvent)}, 11455593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyQueryPool", reinterpret_cast<PFN_vkVoidFunction>(DestroyQueryPool)}, 11456593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyBuffer", reinterpret_cast<PFN_vkVoidFunction>(DestroyBuffer)}, 11457593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyBufferView", reinterpret_cast<PFN_vkVoidFunction>(DestroyBufferView)}, 11458593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyImage", reinterpret_cast<PFN_vkVoidFunction>(DestroyImage)}, 11459593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyImageView", reinterpret_cast<PFN_vkVoidFunction>(DestroyImageView)}, 11460593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyShaderModule", reinterpret_cast<PFN_vkVoidFunction>(DestroyShaderModule)}, 11461593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyPipeline", reinterpret_cast<PFN_vkVoidFunction>(DestroyPipeline)}, 11462593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyPipelineLayout", reinterpret_cast<PFN_vkVoidFunction>(DestroyPipelineLayout)}, 11463593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroySampler", reinterpret_cast<PFN_vkVoidFunction>(DestroySampler)}, 11464593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyDescriptorSetLayout", reinterpret_cast<PFN_vkVoidFunction>(DestroyDescriptorSetLayout)}, 11465593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(DestroyDescriptorPool)}, 11466593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyFramebuffer", reinterpret_cast<PFN_vkVoidFunction>(DestroyFramebuffer)}, 11467593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyRenderPass", reinterpret_cast<PFN_vkVoidFunction>(DestroyRenderPass)}, 11468593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateBuffer", reinterpret_cast<PFN_vkVoidFunction>(CreateBuffer)}, 11469593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateBufferView", reinterpret_cast<PFN_vkVoidFunction>(CreateBufferView)}, 11470593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateImage", reinterpret_cast<PFN_vkVoidFunction>(CreateImage)}, 11471593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateImageView", reinterpret_cast<PFN_vkVoidFunction>(CreateImageView)}, 11472593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateFence", reinterpret_cast<PFN_vkVoidFunction>(CreateFence)}, 11473593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreatePipelineCache", reinterpret_cast<PFN_vkVoidFunction>(CreatePipelineCache)}, 11474593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyPipelineCache", reinterpret_cast<PFN_vkVoidFunction>(DestroyPipelineCache)}, 11475593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkGetPipelineCacheData", reinterpret_cast<PFN_vkVoidFunction>(GetPipelineCacheData)}, 11476593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkMergePipelineCaches", reinterpret_cast<PFN_vkVoidFunction>(MergePipelineCaches)}, 11477593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateGraphicsPipelines", reinterpret_cast<PFN_vkVoidFunction>(CreateGraphicsPipelines)}, 11478593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateComputePipelines", reinterpret_cast<PFN_vkVoidFunction>(CreateComputePipelines)}, 11479593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateSampler", reinterpret_cast<PFN_vkVoidFunction>(CreateSampler)}, 11480593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateDescriptorSetLayout", reinterpret_cast<PFN_vkVoidFunction>(CreateDescriptorSetLayout)}, 11481593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreatePipelineLayout", reinterpret_cast<PFN_vkVoidFunction>(CreatePipelineLayout)}, 11482593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(CreateDescriptorPool)}, 11483593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkResetDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(ResetDescriptorPool)}, 11484593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkAllocateDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(AllocateDescriptorSets)}, 11485593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkFreeDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(FreeDescriptorSets)}, 11486593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkUpdateDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(UpdateDescriptorSets)}, 11487593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateCommandPool", reinterpret_cast<PFN_vkVoidFunction>(CreateCommandPool)}, 11488593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyCommandPool", reinterpret_cast<PFN_vkVoidFunction>(DestroyCommandPool)}, 11489593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkResetCommandPool", reinterpret_cast<PFN_vkVoidFunction>(ResetCommandPool)}, 11490593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateQueryPool", reinterpret_cast<PFN_vkVoidFunction>(CreateQueryPool)}, 11491593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkAllocateCommandBuffers", reinterpret_cast<PFN_vkVoidFunction>(AllocateCommandBuffers)}, 11492593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkFreeCommandBuffers", reinterpret_cast<PFN_vkVoidFunction>(FreeCommandBuffers)}, 11493593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkBeginCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(BeginCommandBuffer)}, 11494593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkEndCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(EndCommandBuffer)}, 11495593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkResetCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(ResetCommandBuffer)}, 11496593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdBindPipeline", reinterpret_cast<PFN_vkVoidFunction>(CmdBindPipeline)}, 11497593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdSetViewport", reinterpret_cast<PFN_vkVoidFunction>(CmdSetViewport)}, 11498593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdSetScissor", reinterpret_cast<PFN_vkVoidFunction>(CmdSetScissor)}, 11499593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdSetLineWidth", reinterpret_cast<PFN_vkVoidFunction>(CmdSetLineWidth)}, 11500593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdSetDepthBias", reinterpret_cast<PFN_vkVoidFunction>(CmdSetDepthBias)}, 11501593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdSetBlendConstants", reinterpret_cast<PFN_vkVoidFunction>(CmdSetBlendConstants)}, 11502593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdSetDepthBounds", reinterpret_cast<PFN_vkVoidFunction>(CmdSetDepthBounds)}, 11503593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdSetStencilCompareMask", reinterpret_cast<PFN_vkVoidFunction>(CmdSetStencilCompareMask)}, 11504593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdSetStencilWriteMask", reinterpret_cast<PFN_vkVoidFunction>(CmdSetStencilWriteMask)}, 11505593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdSetStencilReference", reinterpret_cast<PFN_vkVoidFunction>(CmdSetStencilReference)}, 11506593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdBindDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(CmdBindDescriptorSets)}, 11507593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdBindVertexBuffers", reinterpret_cast<PFN_vkVoidFunction>(CmdBindVertexBuffers)}, 11508593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdBindIndexBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdBindIndexBuffer)}, 11509593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdDraw", reinterpret_cast<PFN_vkVoidFunction>(CmdDraw)}, 11510593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdDrawIndexed", reinterpret_cast<PFN_vkVoidFunction>(CmdDrawIndexed)}, 11511593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdDrawIndirect", reinterpret_cast<PFN_vkVoidFunction>(CmdDrawIndirect)}, 11512593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdDrawIndexedIndirect", reinterpret_cast<PFN_vkVoidFunction>(CmdDrawIndexedIndirect)}, 11513593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdDispatch", reinterpret_cast<PFN_vkVoidFunction>(CmdDispatch)}, 11514593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdDispatchIndirect", reinterpret_cast<PFN_vkVoidFunction>(CmdDispatchIndirect)}, 11515593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdCopyBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyBuffer)}, 11516593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdCopyImage", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyImage)}, 11517593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdBlitImage", reinterpret_cast<PFN_vkVoidFunction>(CmdBlitImage)}, 11518593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdCopyBufferToImage", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyBufferToImage)}, 11519593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdCopyImageToBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyImageToBuffer)}, 11520593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdUpdateBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdUpdateBuffer)}, 11521593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdFillBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdFillBuffer)}, 11522593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdClearColorImage", reinterpret_cast<PFN_vkVoidFunction>(CmdClearColorImage)}, 11523593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdClearDepthStencilImage", reinterpret_cast<PFN_vkVoidFunction>(CmdClearDepthStencilImage)}, 11524593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdClearAttachments", reinterpret_cast<PFN_vkVoidFunction>(CmdClearAttachments)}, 11525593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdResolveImage", reinterpret_cast<PFN_vkVoidFunction>(CmdResolveImage)}, 11526b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski {"vkGetImageSubresourceLayout", reinterpret_cast<PFN_vkVoidFunction>(GetImageSubresourceLayout) }, 11527593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdSetEvent", reinterpret_cast<PFN_vkVoidFunction>(CmdSetEvent)}, 11528593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdResetEvent", reinterpret_cast<PFN_vkVoidFunction>(CmdResetEvent)}, 11529593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdWaitEvents", reinterpret_cast<PFN_vkVoidFunction>(CmdWaitEvents)}, 11530593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdPipelineBarrier", reinterpret_cast<PFN_vkVoidFunction>(CmdPipelineBarrier)}, 11531593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdBeginQuery", reinterpret_cast<PFN_vkVoidFunction>(CmdBeginQuery)}, 11532593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdEndQuery", reinterpret_cast<PFN_vkVoidFunction>(CmdEndQuery)}, 11533593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdResetQueryPool", reinterpret_cast<PFN_vkVoidFunction>(CmdResetQueryPool)}, 11534593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdCopyQueryPoolResults", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyQueryPoolResults)}, 11535593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdPushConstants", reinterpret_cast<PFN_vkVoidFunction>(CmdPushConstants)}, 11536593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdWriteTimestamp", reinterpret_cast<PFN_vkVoidFunction>(CmdWriteTimestamp)}, 11537593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateFramebuffer", reinterpret_cast<PFN_vkVoidFunction>(CreateFramebuffer)}, 11538593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateShaderModule", reinterpret_cast<PFN_vkVoidFunction>(CreateShaderModule)}, 11539593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateRenderPass", reinterpret_cast<PFN_vkVoidFunction>(CreateRenderPass)}, 11540593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdBeginRenderPass", reinterpret_cast<PFN_vkVoidFunction>(CmdBeginRenderPass)}, 11541593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdNextSubpass", reinterpret_cast<PFN_vkVoidFunction>(CmdNextSubpass)}, 11542593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdEndRenderPass", reinterpret_cast<PFN_vkVoidFunction>(CmdEndRenderPass)}, 11543593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdExecuteCommands", reinterpret_cast<PFN_vkVoidFunction>(CmdExecuteCommands)}, 11544593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkSetEvent", reinterpret_cast<PFN_vkVoidFunction>(SetEvent)}, 11545593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkMapMemory", reinterpret_cast<PFN_vkVoidFunction>(MapMemory)}, 11546593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkUnmapMemory", reinterpret_cast<PFN_vkVoidFunction>(UnmapMemory)}, 11547593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkFlushMappedMemoryRanges", reinterpret_cast<PFN_vkVoidFunction>(FlushMappedMemoryRanges)}, 11548593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkInvalidateMappedMemoryRanges", reinterpret_cast<PFN_vkVoidFunction>(InvalidateMappedMemoryRanges)}, 11549593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkAllocateMemory", reinterpret_cast<PFN_vkVoidFunction>(AllocateMemory)}, 11550593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkFreeMemory", reinterpret_cast<PFN_vkVoidFunction>(FreeMemory)}, 11551593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkBindBufferMemory", reinterpret_cast<PFN_vkVoidFunction>(BindBufferMemory)}, 11552593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkGetBufferMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(GetBufferMemoryRequirements)}, 11553593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkGetImageMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(GetImageMemoryRequirements)}, 11554593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkGetQueryPoolResults", reinterpret_cast<PFN_vkVoidFunction>(GetQueryPoolResults)}, 11555593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkBindImageMemory", reinterpret_cast<PFN_vkVoidFunction>(BindImageMemory)}, 11556593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkQueueBindSparse", reinterpret_cast<PFN_vkVoidFunction>(QueueBindSparse)}, 11557593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateSemaphore", reinterpret_cast<PFN_vkVoidFunction>(CreateSemaphore)}, 11558593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateEvent", reinterpret_cast<PFN_vkVoidFunction>(CreateEvent)}, 1155980be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu }; 1156080be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu 1156180be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu for (size_t i = 0; i < ARRAY_SIZE(core_device_commands); i++) { 11562cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!strcmp(core_device_commands[i].name, name)) return core_device_commands[i].proc; 1156380be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu } 1156480be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu 1156580be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu return nullptr; 1156680be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu} 1156780be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu 11568bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic PFN_vkVoidFunction intercept_khr_swapchain_command(const char *name, VkDevice dev) { 1156909a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu static const struct { 1157009a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu const char *name; 1157109a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu PFN_vkVoidFunction proc; 1157209a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu } khr_swapchain_commands[] = { 11573bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkCreateSwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateSwapchainKHR)}, 11574bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkDestroySwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(DestroySwapchainKHR)}, 11575bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkGetSwapchainImagesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetSwapchainImagesKHR)}, 11576bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkAcquireNextImageKHR", reinterpret_cast<PFN_vkVoidFunction>(AcquireNextImageKHR)}, 11577bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkQueuePresentKHR", reinterpret_cast<PFN_vkVoidFunction>(QueuePresentKHR)}, 1157809a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu }; 11579c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young layer_data *dev_data = nullptr; 1158009a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu 115813f6f8132355ebdae2736b31fc20de2ac60a70310Chia-I Wu if (dev) { 1158256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis dev_data = GetLayerDataPtr(get_dispatch_key(dev), layer_data_map); 11583cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!dev_data->device_extensions.wsi_enabled) return nullptr; 115843f6f8132355ebdae2736b31fc20de2ac60a70310Chia-I Wu } 1158509a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu 1158609a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu for (size_t i = 0; i < ARRAY_SIZE(khr_swapchain_commands); i++) { 11587cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!strcmp(khr_swapchain_commands[i].name, name)) return khr_swapchain_commands[i].proc; 1158809a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu } 1158909a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu 11590c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young if (dev_data) { 11591cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!dev_data->device_extensions.wsi_display_swapchain_enabled) return nullptr; 11592c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young } 11593c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young 11594cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!strcmp("vkCreateSharedSwapchainsKHR", name)) return reinterpret_cast<PFN_vkVoidFunction>(CreateSharedSwapchainsKHR); 11595c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young 1159609a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu return nullptr; 11597747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 11598747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11599bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic PFN_vkVoidFunction intercept_khr_surface_command(const char *name, VkInstance instance) { 11600747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes static const struct { 11601747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes const char *name; 11602747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes PFN_vkVoidFunction proc; 11603747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes bool instance_layer_data::*enable; 11604747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes } khr_surface_commands[] = { 11605747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_ANDROID_KHR 11606747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes {"vkCreateAndroidSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateAndroidSurfaceKHR), 11607bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::androidSurfaceExtensionEnabled}, 11608cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_ANDROID_KHR 11609747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_MIR_KHR 11610747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes {"vkCreateMirSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateMirSurfaceKHR), 11611bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::mirSurfaceExtensionEnabled}, 11612cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_MIR_KHR 11613747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_WAYLAND_KHR 11614747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes {"vkCreateWaylandSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateWaylandSurfaceKHR), 11615bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::waylandSurfaceExtensionEnabled}, 11616cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_WAYLAND_KHR 11617747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_WIN32_KHR 11618747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes {"vkCreateWin32SurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateWin32SurfaceKHR), 11619bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::win32SurfaceExtensionEnabled}, 11620cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_WIN32_KHR 11621747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_XCB_KHR 11622747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes {"vkCreateXcbSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateXcbSurfaceKHR), 11623bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::xcbSurfaceExtensionEnabled}, 11624cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_XCB_KHR 11625747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_XLIB_KHR 11626747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes {"vkCreateXlibSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateXlibSurfaceKHR), 11627bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::xlibSurfaceExtensionEnabled}, 11628cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_XLIB_KHR 11629bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkCreateDisplayPlaneSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateDisplayPlaneSurfaceKHR), 11630bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::displayExtensionEnabled}, 11631747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes {"vkDestroySurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(DestroySurfaceKHR), 11632bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::surfaceExtensionEnabled}, 1163340921785005eb449ec7c18229f0d84c879708b8aChris Forbes {"vkGetPhysicalDeviceSurfaceCapabilitiesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceCapabilitiesKHR), 11634bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::surfaceExtensionEnabled}, 11635418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes {"vkGetPhysicalDeviceSurfaceSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceSupportKHR), 11636bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::surfaceExtensionEnabled}, 116379e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes {"vkGetPhysicalDeviceSurfacePresentModesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfacePresentModesKHR), 11638bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::surfaceExtensionEnabled}, 116395faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes {"vkGetPhysicalDeviceSurfaceFormatsKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceFormatsKHR), 11640bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::surfaceExtensionEnabled}, 11641747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes }; 11642747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11643747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_layer_data *instance_data = nullptr; 11644747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (instance) { 1164556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 11646747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes } 11647747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11648747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes for (size_t i = 0; i < ARRAY_SIZE(khr_surface_commands); i++) { 11649747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (!strcmp(khr_surface_commands[i].name, name)) { 11650cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (instance_data && !(instance_data->*(khr_surface_commands[i].enable))) return nullptr; 11651747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes return khr_surface_commands[i].proc; 11652747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes } 11653747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes } 11654747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11655747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes return nullptr; 1165609a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu} 1165709a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu 1165843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic PFN_vkVoidFunction intercept_extension_instance_commands(const char *name, VkInstance instance) { 1165943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis static const struct { 1166043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis const char *name; 1166143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis PFN_vkVoidFunction proc; 1166243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis bool instance_layer_data::*enable; 1166343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } instance_extension_commands[] = { 1166443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis {"vkGetPhysicalDeviceQueueFamilyProperties2KHR", 1166543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceQueueFamilyProperties2KHR)}, 1166643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis }; 1166743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis 1166843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis for (size_t i = 0; i < ARRAY_SIZE(instance_extension_commands); i++) { 1166943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis if (!strcmp(instance_extension_commands[i].name, name)) { 1167043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis return instance_extension_commands[i].proc; 1167143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 1167243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 1167343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis return nullptr; 1167443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis} 11675b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 11676cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski} // namespace core_validation 11677d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu 11678d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu// vk_layer_logging.h expects these to be defined 11679d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu 11680bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugReportCallbackEXT(VkInstance instance, 11681bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkDebugReportCallbackCreateInfoEXT *pCreateInfo, 11682bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, 11683bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDebugReportCallbackEXT *pMsgCallback) { 1168489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu return core_validation::CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback); 11685d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu} 11686d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu 11687bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT msgCallback, 11688bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator) { 1168989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu core_validation::DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator); 11690d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu} 11691d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu 11692bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL vkDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, 11693bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDebugReportObjectTypeEXT objType, uint64_t object, size_t location, 11694bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski int32_t msgCode, const char *pLayerPrefix, const char *pMsg) { 1169589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu core_validation::DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg); 11696d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu} 11697d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu 11698a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu// loader-layer interface v0, just wrappers since there is only a layer 11699d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu 11700bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, 11701bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkExtensionProperties *pProperties) { 11702a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu return core_validation::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties); 1170308939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu} 1170408939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu 11705bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount, 11706bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkLayerProperties *pProperties) { 11707a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu return core_validation::EnumerateInstanceLayerProperties(pCount, pProperties); 1170808939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu} 1170908939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu 11710bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, 11711bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkLayerProperties *pProperties) { 11712a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu // the layer command handles VK_NULL_HANDLE just fine internally 11713a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu assert(physicalDevice == VK_NULL_HANDLE); 11714a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu return core_validation::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties); 11715d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu} 11716d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu 11717d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I WuVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, 11718d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu const char *pLayerName, uint32_t *pCount, 11719d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu VkExtensionProperties *pProperties) { 11720a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu // the layer command handles VK_NULL_HANDLE just fine internally 11721a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu assert(physicalDevice == VK_NULL_HANDLE); 11722a8f4a23b1e9c068717eda47cc583a93f447c77e3Chia-I Wu return core_validation::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties); 11723d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu} 11724d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu 11725d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I WuVK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) { 1172689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu return core_validation::GetDeviceProcAddr(dev, funcName); 11727d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu} 11728d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu 11729d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I WuVK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) { 1173089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu return core_validation::GetInstanceProcAddr(instance, funcName); 1173108939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu} 11732b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 11733bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance, 11734bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const char *funcName) { 11735b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young return core_validation::GetPhysicalDeviceProcAddr(instance, funcName); 11736b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young} 11737b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 11738b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark YoungVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) { 11739b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young assert(pVersionStruct != NULL); 11740b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT); 11741b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 11742b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young // Fill in the function pointers if our version is at least capable of having the structure contain them. 11743b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young if (pVersionStruct->loaderLayerInterfaceVersion >= 2) { 11744b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr; 11745b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr; 11746b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young pVersionStruct->pfnGetPhysicalDeviceProcAddr = vk_layerGetPhysicalDeviceProcAddr; 11747b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young } 11748b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 11749b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young if (pVersionStruct->loaderLayerInterfaceVersion < CURRENT_LOADER_LAYER_INTERFACE_VERSION) { 11750b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young core_validation::loader_layer_if_version = pVersionStruct->loaderLayerInterfaceVersion; 11751b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young } else if (pVersionStruct->loaderLayerInterfaceVersion > CURRENT_LOADER_LAYER_INTERFACE_VERSION) { 11752b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young pVersionStruct->loaderLayerInterfaceVersion = CURRENT_LOADER_LAYER_INTERFACE_VERSION; 11753b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young } 11754b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 11755b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young return VK_SUCCESS; 11756b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young} 11757