core_validation.cpp revision 2664122d97c3f0a98b3e5d12833bbb20196ca837
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 Ehlis// fwd decls 1065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstruct shader_module; 1075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 108f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbesstruct instance_layer_data { 109d3578035fec44db2380099c2f59d3e4d8e0b98d6Chris Forbes VkInstance instance = VK_NULL_HANDLE; 110d3578035fec44db2380099c2f59d3e4d8e0b98d6Chris Forbes debug_report_data *report_data = nullptr; 1115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::vector<VkDebugReportCallbackEXT> logging_callback; 1129172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes VkLayerInstanceDispatchTable dispatch_table; 1139172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes 114219f00ffed576643641976122fa1db8e5fce5dc1Chris Forbes CALL_STATE vkEnumeratePhysicalDevicesState = UNCALLED; 115219f00ffed576643641976122fa1db8e5fce5dc1Chris Forbes uint32_t physical_devices_count = 0; 116b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young CALL_STATE vkEnumeratePhysicalDeviceGroupsState = UNCALLED; 117b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young uint32_t physical_device_groups_count = 0; 118219f00ffed576643641976122fa1db8e5fce5dc1Chris Forbes CHECK_DISABLED disabled = {}; 119219f00ffed576643641976122fa1db8e5fce5dc1Chris Forbes 120f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbes unordered_map<VkPhysicalDevice, PHYSICAL_DEVICE_STATE> physical_device_map; 121747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes unordered_map<VkSurfaceKHR, SURFACE_STATE> surface_map; 122747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 123747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes bool surfaceExtensionEnabled = false; 124747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes bool displayExtensionEnabled = false; 125747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes bool androidSurfaceExtensionEnabled = false; 126747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes bool mirSurfaceExtensionEnabled = false; 127747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes bool waylandSurfaceExtensionEnabled = false; 128747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes bool win32SurfaceExtensionEnabled = false; 129747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes bool xcbSurfaceExtensionEnabled = false; 130747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes bool xlibSurfaceExtensionEnabled = false; 131f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbes}; 132f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbes 133f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbesstruct layer_data { 134f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbes debug_report_data *report_data = nullptr; 1354a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkLayerDispatchTable dispatch_table; 13694c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis 137d3578035fec44db2380099c2f59d3e4d8e0b98d6Chris Forbes devExts device_extensions = {}; 138cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski unordered_set<VkQueue> queues; // All queues under given device 1395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Global set of all cmdBuffers that are inFlight on this device 1405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unordered_set<VkCommandBuffer> globalInFlightCmdBuffers; 1415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Layer specific data 142d31a44af6da568692a73201825459689c9431867Tobin Ehlis unordered_map<VkSampler, unique_ptr<SAMPLER_STATE>> samplerMap; 14379fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis unordered_map<VkImageView, unique_ptr<IMAGE_VIEW_STATE>> imageViewMap; 1441facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis unordered_map<VkImage, unique_ptr<IMAGE_STATE>> imageMap; 14539267c0c27b8f032f05a6747eb02d4508247fdc1Tobin Ehlis unordered_map<VkBufferView, unique_ptr<BUFFER_VIEW_STATE>> bufferViewMap; 1465cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis unordered_map<VkBuffer, unique_ptr<BUFFER_STATE>> bufferMap; 1474c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis unordered_map<VkPipeline, PIPELINE_STATE *> pipelineMap; 1488d6a38de0389036581ada119e548180c614fe0efChris Forbes unordered_map<VkCommandPool, COMMAND_POOL_NODE> commandPoolMap; 149a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis unordered_map<VkDescriptorPool, DESCRIPTOR_POOL_STATE *> descriptorPoolMap; 150397d27da37095073c8b86f9ff5289d0a39ce486eTobin Ehlis unordered_map<VkDescriptorSet, cvdescriptorset::DescriptorSet *> setMap; 151cb9ce9e05b8e939d3da35c64997c70049877f4feTobin Ehlis unordered_map<VkDescriptorSetLayout, cvdescriptorset::DescriptorSetLayout *> descriptorSetLayoutMap; 1525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unordered_map<VkPipelineLayout, PIPELINE_LAYOUT_NODE> pipelineLayoutMap; 15357fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis unordered_map<VkDeviceMemory, unique_ptr<DEVICE_MEM_INFO>> memObjMap; 1545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unordered_map<VkFence, FENCE_NODE> fenceMap; 15536c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlis unordered_map<VkQueue, QUEUE_STATE> queueMap; 1564710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis unordered_map<VkEvent, EVENT_STATE> eventMap; 1575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unordered_map<QueryObject, bool> queryToStateMap; 1585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unordered_map<VkQueryPool, QUERY_POOL_NODE> queryPoolMap; 1595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unordered_map<VkSemaphore, SEMAPHORE_NODE> semaphoreMap; 16072d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis unordered_map<VkCommandBuffer, GLOBAL_CB_NODE *> commandBufferMap; 161c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis unordered_map<VkFramebuffer, unique_ptr<FRAMEBUFFER_STATE>> frameBufferMap; 1625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unordered_map<VkImage, vector<ImageSubresourcePair>> imageSubresourceMap; 1635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unordered_map<ImageSubresourcePair, IMAGE_LAYOUT_NODE> imageLayoutMap; 164127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis unordered_map<VkRenderPass, unique_ptr<RENDER_PASS_STATE>> renderPassMap; 165918c283ac4f8c604b79abd0c8b5706d2a7352a34Chris Forbes unordered_map<VkShaderModule, unique_ptr<shader_module>> shaderModuleMap; 1666246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski unordered_map<VkDescriptorUpdateTemplateKHR, unique_ptr<TEMPLATE_STATE>> desc_template_map; 16707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski 168d3578035fec44db2380099c2f59d3e4d8e0b98d6Chris Forbes VkDevice device = VK_NULL_HANDLE; 169ec85232c4d8d9ddf7d2ae57cb8203c5ab52c1106Mark Lobodzinski VkPhysicalDevice physical_device = VK_NULL_HANDLE; 1705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 171cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski instance_layer_data *instance_data = nullptr; // from device to enclosing instance 17207a464bd7fec9583f346b8c4b8d43c88d2e9ffa4Chris Forbes 173f71dd305f197826a61f398bff725267a20ea1d90Chris Forbes VkPhysicalDeviceFeatures enabled_features = {}; 1745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Device specific data 175d3578035fec44db2380099c2f59d3e4d8e0b98d6Chris Forbes PHYS_DEV_PROPERTIES_NODE phys_dev_properties = {}; 176d3578035fec44db2380099c2f59d3e4d8e0b98d6Chris Forbes VkPhysicalDeviceMemoryProperties phys_dev_mem_props = {}; 177e47dbc3f3340fa177d877a67b2adb76a570027e5Mark Lobodzinski VkPhysicalDeviceProperties phys_dev_props = {}; 1785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}; 1795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 180b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis// TODO : Do we need to guard access to layer_data_map w/ lock? 181b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlisstatic unordered_map<void *, layer_data *> layer_data_map; 182f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbesstatic unordered_map<void *, instance_layer_data *> instance_layer_data_map; 183b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis 184b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Youngstatic uint32_t loader_layer_if_version = CURRENT_LOADER_LAYER_INTERFACE_VERSION; 185b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 186e11120777bcd1543455d1de54b89292879bcd2bbChia-I Wustatic const VkLayerProperties global_layer = { 187f1ea418f193d10a8455cdf47e0eeeeb1f4d8b5bfJon Ashburn "VK_LAYER_LUNARG_core_validation", VK_LAYER_API_VERSION, 1, "LunarG Validation Layer", 188e11120777bcd1543455d1de54b89292879bcd2bbChia-I Wu}; 1895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 190cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskitemplate <class TCreateInfo> 191cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskivoid ValidateLayerOrdering(const TCreateInfo &createInfo) { 1925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool foundLayer = false; 1935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < createInfo.enabledLayerCount; ++i) { 194e11120777bcd1543455d1de54b89292879bcd2bbChia-I Wu if (!strcmp(createInfo.ppEnabledLayerNames[i], global_layer.layerName)) { 1955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis foundLayer = true; 1965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 1975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // This has to be logged to console as we don't have a callback at this point. 1985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!foundLayer && !strcmp(createInfo.ppEnabledLayerNames[0], "VK_LAYER_GOOGLE_unique_objects")) { 199bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski LOGCONSOLE("Cannot activate layer VK_LAYER_GOOGLE_unique_objects prior to activating %s.", global_layer.layerName); 2005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 2015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 2025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 2035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Code imported from shader_checker 2055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic void build_def_index(shader_module *); 2065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// A forward iterator over spirv instructions. Provides easy access to len, opcode, and content words 2085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// without the caller needing to care too much about the physical SPIRV module layout. 2095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstruct spirv_inst_iter { 2105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::vector<uint32_t>::const_iterator zero; 2115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::vector<uint32_t>::const_iterator it; 2125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 213b95616f79b105741b1399b01d527a8ef3b7ccfb7Chris Forbes uint32_t len() { 214b95616f79b105741b1399b01d527a8ef3b7ccfb7Chris Forbes auto result = *it >> 16; 215b95616f79b105741b1399b01d527a8ef3b7ccfb7Chris Forbes assert(result > 0); 216b95616f79b105741b1399b01d527a8ef3b7ccfb7Chris Forbes return result; 217b95616f79b105741b1399b01d527a8ef3b7ccfb7Chris Forbes } 218b95616f79b105741b1399b01d527a8ef3b7ccfb7Chris Forbes 2195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t opcode() { return *it & 0x0ffffu; } 220b95616f79b105741b1399b01d527a8ef3b7ccfb7Chris Forbes 221b95616f79b105741b1399b01d527a8ef3b7ccfb7Chris Forbes uint32_t const &word(unsigned n) { 222b95616f79b105741b1399b01d527a8ef3b7ccfb7Chris Forbes assert(n < len()); 223b95616f79b105741b1399b01d527a8ef3b7ccfb7Chris Forbes return it[n]; 224b95616f79b105741b1399b01d527a8ef3b7ccfb7Chris Forbes } 225b95616f79b105741b1399b01d527a8ef3b7ccfb7Chris Forbes 2265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t offset() { return (uint32_t)(it - zero); } 2275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis spirv_inst_iter() {} 2295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis spirv_inst_iter(std::vector<uint32_t>::const_iterator zero, std::vector<uint32_t>::const_iterator it) : zero(zero), it(it) {} 2315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool operator==(spirv_inst_iter const &other) { return it == other.it; } 2335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool operator!=(spirv_inst_iter const &other) { return it != other.it; } 2355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 236cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski spirv_inst_iter operator++(int) { // x++ 2375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis spirv_inst_iter ii = *this; 2385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis it += len(); 2395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return ii; 2405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 2415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 242cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski spirv_inst_iter operator++() { // ++x; 2435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis it += len(); 2445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return *this; 2455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 2465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 24725002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // The iterator and the value are the same thing. 2485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis spirv_inst_iter &operator*() { return *this; } 2495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis spirv_inst_iter const &operator*() const { return *this; } 2505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}; 2515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstruct shader_module { 25325002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // The spirv image itself 2545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis vector<uint32_t> words; 25525002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // A mapping of <id> to the first word of its def. this is useful because walking type 25625002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // trees, constant expressions, etc requires jumping all over the instruction stream. 2575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unordered_map<unsigned, unsigned> def_index; 258c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski bool has_valid_spirv; 2595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis shader_module(VkShaderModuleCreateInfo const *pCreateInfo) 2615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis : words((uint32_t *)pCreateInfo->pCode, (uint32_t *)pCreateInfo->pCode + pCreateInfo->codeSize / sizeof(uint32_t)), 262c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski def_index(), 263c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski has_valid_spirv(true) { 2645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis build_def_index(this); 2655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 2665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 267c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski shader_module() : has_valid_spirv(false) {} 268c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski 26925002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Expose begin() / end() to enable range-based for 270cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski spirv_inst_iter begin() const { return spirv_inst_iter(words.begin(), words.begin() + 5); } // First insn 271cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski spirv_inst_iter end() const { return spirv_inst_iter(words.begin(), words.end()); } // Just past last insn 27225002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Given an offset into the module, produce an iterator there. 2735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis spirv_inst_iter at(unsigned offset) const { return spirv_inst_iter(words.begin(), words.begin() + offset); } 2745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 27525002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Gets an iterator to the definition of an id 2765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis spirv_inst_iter get_def(unsigned id) const { 2775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto it = def_index.find(id); 2785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (it == def_index.end()) { 2795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return end(); 2805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 2815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return at(it->second); 2825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 2835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}; 2845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// TODO : This can be much smarter, using separate locks for separate global data 286b9e992386a44404152747d66817a733aa127e281Jeremy Hayesstatic std::mutex global_lock; 287593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 28879fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis// Return IMAGE_VIEW_STATE ptr for specified imageView or else NULL 2899a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisIMAGE_VIEW_STATE *GetImageViewState(const layer_data *dev_data, VkImageView image_view) { 2902c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis auto iv_it = dev_data->imageViewMap.find(image_view); 2912c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis if (iv_it == dev_data->imageViewMap.end()) { 2922c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis return nullptr; 2932c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis } 2942c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis return iv_it->second.get(); 2952c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis} 2969a55ca3674bb3fac3fbdfca9515a16a224aa9055Tobin Ehlis// Return sampler node ptr for specified sampler or else NULL 2979a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisSAMPLER_STATE *GetSamplerState(const layer_data *dev_data, VkSampler sampler) { 2982c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis auto sampler_it = dev_data->samplerMap.find(sampler); 2992c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis if (sampler_it == dev_data->samplerMap.end()) { 3009a55ca3674bb3fac3fbdfca9515a16a224aa9055Tobin Ehlis return nullptr; 3019a55ca3674bb3fac3fbdfca9515a16a224aa9055Tobin Ehlis } 3029a55ca3674bb3fac3fbdfca9515a16a224aa9055Tobin Ehlis return sampler_it->second.get(); 3039a55ca3674bb3fac3fbdfca9515a16a224aa9055Tobin Ehlis} 3045cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis// Return image state ptr for specified image or else NULL 3059a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisIMAGE_STATE *GetImageState(const layer_data *dev_data, VkImage image) { 3066d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis auto img_it = dev_data->imageMap.find(image); 3076d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis if (img_it == dev_data->imageMap.end()) { 3086d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis return nullptr; 3096d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis } 3106d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis return img_it->second.get(); 3116d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis} 3125cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis// Return buffer state ptr for specified buffer or else NULL 3139a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisBUFFER_STATE *GetBufferState(const layer_data *dev_data, VkBuffer buffer) { 3142c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis auto buff_it = dev_data->bufferMap.find(buffer); 3152c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis if (buff_it == dev_data->bufferMap.end()) { 3168718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis return nullptr; 3178718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis } 3188718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis return buff_it->second.get(); 3198718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis} 320b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis// Return swapchain node for specified swapchain or else NULL 3219a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisSWAPCHAIN_NODE *GetSwapchainNode(const layer_data *dev_data, VkSwapchainKHR swapchain) { 322b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis auto swp_it = dev_data->device_extensions.swapchainMap.find(swapchain); 323b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis if (swp_it == dev_data->device_extensions.swapchainMap.end()) { 324b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis return nullptr; 325b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis } 3263f687bf405355f3eec6bd1bc0e8d04daba37a0f9Tobin Ehlis return swp_it->second.get(); 327b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis} 328170dc65b45f6bcdec47e02b3aa19435e55b32804Tobin Ehlis// Return swapchain for specified image or else NULL 3299a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisVkSwapchainKHR GetSwapchainFromImage(const layer_data *dev_data, VkImage image) { 330170dc65b45f6bcdec47e02b3aa19435e55b32804Tobin Ehlis auto img_it = dev_data->device_extensions.imageToSwapchainMap.find(image); 331170dc65b45f6bcdec47e02b3aa19435e55b32804Tobin Ehlis if (img_it == dev_data->device_extensions.imageToSwapchainMap.end()) { 332170dc65b45f6bcdec47e02b3aa19435e55b32804Tobin Ehlis return VK_NULL_HANDLE; 333170dc65b45f6bcdec47e02b3aa19435e55b32804Tobin Ehlis } 334170dc65b45f6bcdec47e02b3aa19435e55b32804Tobin Ehlis return img_it->second; 335170dc65b45f6bcdec47e02b3aa19435e55b32804Tobin Ehlis} 3362f2db584f5d79892bd84d0a24b8ca3499985a5c2Tobin Ehlis// Return buffer node ptr for specified buffer or else NULL 3379a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisBUFFER_VIEW_STATE *GetBufferViewState(const layer_data *dev_data, VkBufferView buffer_view) { 33851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis auto bv_it = dev_data->bufferViewMap.find(buffer_view); 33951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (bv_it == dev_data->bufferViewMap.end()) { 3402f2db584f5d79892bd84d0a24b8ca3499985a5c2Tobin Ehlis return nullptr; 3412f2db584f5d79892bd84d0a24b8ca3499985a5c2Tobin Ehlis } 3422f2db584f5d79892bd84d0a24b8ca3499985a5c2Tobin Ehlis return bv_it->second.get(); 3432f2db584f5d79892bd84d0a24b8ca3499985a5c2Tobin Ehlis} 3448718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis 3459a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisFENCE_NODE *GetFenceNode(layer_data *dev_data, VkFence fence) { 34666fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes auto it = dev_data->fenceMap.find(fence); 34766fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes if (it == dev_data->fenceMap.end()) { 34866fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes return nullptr; 34966fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes } 35066fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes return &it->second; 35166fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes} 35266fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes 3539a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisEVENT_STATE *GetEventNode(layer_data *dev_data, VkEvent event) { 3549556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis auto it = dev_data->eventMap.find(event); 3559556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis if (it == dev_data->eventMap.end()) { 3569556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis return nullptr; 3579556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis } 3589556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis return &it->second; 3599556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis} 3609556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis 3619a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisQUERY_POOL_NODE *GetQueryPoolNode(layer_data *dev_data, VkQueryPool query_pool) { 362ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis auto it = dev_data->queryPoolMap.find(query_pool); 363ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis if (it == dev_data->queryPoolMap.end()) { 364ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis return nullptr; 365ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis } 366ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis return &it->second; 367ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis} 368ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis 3699a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisQUEUE_STATE *GetQueueState(layer_data *dev_data, VkQueue queue) { 37066fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes auto it = dev_data->queueMap.find(queue); 37166fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes if (it == dev_data->queueMap.end()) { 37266fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes return nullptr; 37366fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes } 37466fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes return &it->second; 37566fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes} 37666fb98d19a758f79dd11ba354e47d0c66c6aac1eChris Forbes 3779a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisSEMAPHORE_NODE *GetSemaphoreNode(layer_data *dev_data, VkSemaphore semaphore) { 3785e92f3cfdca6a52a3dcefd053c41f728bd036cebChris Forbes auto it = dev_data->semaphoreMap.find(semaphore); 3795e92f3cfdca6a52a3dcefd053c41f728bd036cebChris Forbes if (it == dev_data->semaphoreMap.end()) { 3805e92f3cfdca6a52a3dcefd053c41f728bd036cebChris Forbes return nullptr; 3815e92f3cfdca6a52a3dcefd053c41f728bd036cebChris Forbes } 3825e92f3cfdca6a52a3dcefd053c41f728bd036cebChris Forbes return &it->second; 3835e92f3cfdca6a52a3dcefd053c41f728bd036cebChris Forbes} 3845e92f3cfdca6a52a3dcefd053c41f728bd036cebChris Forbes 3859a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisCOMMAND_POOL_NODE *GetCommandPoolNode(layer_data *dev_data, VkCommandPool pool) { 3868d6a38de0389036581ada119e548180c614fe0efChris Forbes auto it = dev_data->commandPoolMap.find(pool); 3878d6a38de0389036581ada119e548180c614fe0efChris Forbes if (it == dev_data->commandPoolMap.end()) { 3888d6a38de0389036581ada119e548180c614fe0efChris Forbes return nullptr; 3898d6a38de0389036581ada119e548180c614fe0efChris Forbes } 3908d6a38de0389036581ada119e548180c614fe0efChris Forbes return &it->second; 3918d6a38de0389036581ada119e548180c614fe0efChris Forbes} 3923bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes 3939a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisPHYSICAL_DEVICE_STATE *GetPhysicalDeviceState(instance_layer_data *instance_data, VkPhysicalDevice phys) { 394f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbes auto it = instance_data->physical_device_map.find(phys); 395f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbes if (it == instance_data->physical_device_map.end()) { 3963bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes return nullptr; 3973bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes } 3983bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes return &it->second; 3993bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes} 4003bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes 4019a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisSURFACE_STATE *GetSurfaceState(instance_layer_data *instance_data, VkSurfaceKHR surface) { 402747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes auto it = instance_data->surface_map.find(surface); 403747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (it == instance_data->surface_map.end()) { 404747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes return nullptr; 405747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes } 406747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes return &it->second; 407747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 408747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 409f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis// Return ptr to memory binding for given handle of specified type 41051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic BINDABLE *GetObjectMemBinding(layer_data *dev_data, uint64_t handle, VkDebugReportObjectTypeEXT type) { 4115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis switch (type) { 412cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT: 4139a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis return GetImageState(dev_data, VkImage(handle)); 414cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT: 4159a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis return GetBufferState(dev_data, VkBuffer(handle)); 416cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 417cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 4185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 41994c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis return nullptr; 4205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 42172d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis// prototype 4229a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisGLOBAL_CB_NODE *GetCBNode(layer_data const *, const VkCommandBuffer); 42372d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis 4245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Return ptr to info in map container containing mem, or NULL if not found 4255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Calls to this function should be wrapped in mutex 4269a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisDEVICE_MEM_INFO *GetMemObjInfo(const layer_data *dev_data, const VkDeviceMemory mem) { 42757fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis auto mem_it = dev_data->memObjMap.find(mem); 42857fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis if (mem_it == dev_data->memObjMap.end()) { 4295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return NULL; 4305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 43157fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis return mem_it->second.get(); 4325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 4335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 43451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic void add_mem_obj_info(layer_data *dev_data, void *object, const VkDeviceMemory mem, 4355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkMemoryAllocateInfo *pAllocateInfo) { 4365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(object != NULL); 4375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 43851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->memObjMap[mem] = unique_ptr<DEVICE_MEM_INFO>(new DEVICE_MEM_INFO(object, mem, pAllocateInfo)); 4395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 440dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis 441dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis// Helper function to print lowercase string of object type 442dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis// TODO: Unify string helper functions, this should really come out of a string helper if not there already 443dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlisstatic const char *object_type_to_string(VkDebugReportObjectTypeEXT type) { 444dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis switch (type) { 445cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT: 446cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "image"; 447cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT: 448cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "buffer"; 449cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT: 450cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "image view"; 451cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT: 452cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "buffer view"; 453cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT: 454cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "swapchain"; 455cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT: 456cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "descriptor set"; 457cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT: 458cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "framebuffer"; 459cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT: 460cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "event"; 461cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT: 462cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "query pool"; 463cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT: 464cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "descriptor pool"; 465cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT: 466cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "command pool"; 467cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT: 468cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "pipeline"; 469cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT: 470cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "sampler"; 471cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT: 472cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "renderpass"; 473cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT: 474cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "device memory"; 475cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT: 476cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "semaphore"; 477cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 478cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "unknown"; 479dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis } 480dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis} 481dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis 482cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis// For given bound_object_handle, bound to given mem allocation, verify that the range for the bound object is valid 483f989de4217bce0f293121d0da53dc8328276370fTobin Ehlisstatic bool ValidateMemoryIsValid(layer_data *dev_data, VkDeviceMemory mem, uint64_t bound_object_handle, 484dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis VkDebugReportObjectTypeEXT type, const char *functionName) { 4859a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *mem_info = GetMemObjInfo(dev_data, mem); 486f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis if (mem_info) { 487f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis if (!mem_info->bound_ranges[bound_object_handle].valid) { 488f48a83f5b5548cd46a12770c7542ff902537ad3eKarl Schultz return log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 489ea8e85ade623a09c601d939622cbd7740d8d66c9Tobin Ehlis reinterpret_cast<uint64_t &>(mem), __LINE__, MEMTRACK_INVALID_MEM_REGION, "MEM", 490dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis "%s: Cannot read invalid region of memory allocation 0x%" PRIx64 " for bound %s object 0x%" PRIx64 491dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis ", please fill the memory before using.", 492dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis functionName, reinterpret_cast<uint64_t &>(mem), object_type_to_string(type), bound_object_handle); 493f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis } 494f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis } 495f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis return false; 496f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis} 4971facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis// For given image_state 4981facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis// If mem is special swapchain key, then verify that image_state valid member is true 499f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis// Else verify that the image's bound memory range is valid 50060568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinskibool ValidateImageMemoryIsValid(layer_data *dev_data, IMAGE_STATE *image_state, const char *functionName) { 501e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis if (image_state->binding.mem == MEMTRACKER_SWAP_CHAIN_IMAGE_KEY) { 5021facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis if (!image_state->valid) { 503f48a83f5b5548cd46a12770c7542ff902537ad3eKarl Schultz return log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 504e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis reinterpret_cast<uint64_t &>(image_state->binding.mem), __LINE__, MEMTRACK_INVALID_MEM_REGION, "MEM", 505414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller "%s: Cannot read invalid swapchain image 0x%" PRIx64 ", please fill the memory before using.", 5061facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis functionName, reinterpret_cast<uint64_t &>(image_state->image)); 5075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 509e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis return ValidateMemoryIsValid(dev_data, image_state->binding.mem, reinterpret_cast<uint64_t &>(image_state->image), 510dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, functionName); 5115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 5135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 5145cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis// For given buffer_state, verify that the range it's bound to is valid 515c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinskibool ValidateBufferMemoryIsValid(layer_data *dev_data, BUFFER_STATE *buffer_state, const char *functionName) { 5165cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis return ValidateMemoryIsValid(dev_data, buffer_state->binding.mem, reinterpret_cast<uint64_t &>(buffer_state->buffer), 517dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, functionName); 518f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis} 519f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis// For the given memory allocation, set the range bound by the given handle object to the valid param value 520f989de4217bce0f293121d0da53dc8328276370fTobin Ehlisstatic void SetMemoryValid(layer_data *dev_data, VkDeviceMemory mem, uint64_t handle, bool valid) { 5219a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *mem_info = GetMemObjInfo(dev_data, mem); 522f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis if (mem_info) { 523f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis mem_info->bound_ranges[handle].valid = valid; 524f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis } 525f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis} 526f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis// For given image node 5271facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis// If mem is special swapchain key, then set entire image_state to valid param value 528f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis// Else set the image's bound memory range to valid param value 529623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinskivoid SetImageMemoryValid(layer_data *dev_data, IMAGE_STATE *image_state, bool valid) { 530e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis if (image_state->binding.mem == MEMTRACKER_SWAP_CHAIN_IMAGE_KEY) { 5311facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis image_state->valid = valid; 5325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 533e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis SetMemoryValid(dev_data, image_state->binding.mem, reinterpret_cast<uint64_t &>(image_state->image), valid); 5345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 536f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis// For given buffer node set the buffer's bound memory range to valid param value 537c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinskivoid SetBufferMemoryValid(layer_data *dev_data, BUFFER_STATE *buffer_state, bool valid) { 5385cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis SetMemoryValid(dev_data, buffer_state->binding.mem, reinterpret_cast<uint64_t &>(buffer_state->buffer), valid); 539f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis} 5405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Find CB Info and add mem reference to list container 5415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Find Mem Obj Info and add CB reference to list container 542e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool update_cmd_buf_and_mem_references(layer_data *dev_data, const VkCommandBuffer cb, const VkDeviceMemory mem, 543e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves const char *apiName) { 54483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 5455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Skip validation if this image was created through WSI 5475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (mem != MEMTRACKER_SWAP_CHAIN_IMAGE_KEY) { 5485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // First update CB binding in MemObj mini CB list 5499a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *pMemInfo = GetMemObjInfo(dev_data, mem); 5505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pMemInfo) { 5515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Now update CBInfo's Mem reference list 5529a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *cb_node = GetCBNode(dev_data, cb); 553d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis pMemInfo->cb_bindings.insert(cb_node); 5545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODO: keep track of all destroyed CBs so we know if this is a stale or simply invalid object 555d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis if (cb_node) { 556d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis cb_node->memObjs.insert(mem); 5575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 56083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis return skip_call; 5615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 562ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis 56356f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis// Create binding link between given sampler and command buffer node 564d31a44af6da568692a73201825459689c9431867Tobin Ehlisvoid AddCommandBufferBindingSampler(GLOBAL_CB_NODE *cb_node, SAMPLER_STATE *sampler_state) { 565d31a44af6da568692a73201825459689c9431867Tobin Ehlis sampler_state->cb_bindings.insert(cb_node); 566d31a44af6da568692a73201825459689c9431867Tobin Ehlis cb_node->object_bindings.insert( 567d31a44af6da568692a73201825459689c9431867Tobin Ehlis {reinterpret_cast<uint64_t &>(sampler_state->sampler), VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT}); 56856f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis} 56956f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis 57056f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis// Create binding link between given image node and command buffer node 5711facd2c91911508b9fb61f54a56269841299f663Tobin Ehlisvoid AddCommandBufferBindingImage(const layer_data *dev_data, GLOBAL_CB_NODE *cb_node, IMAGE_STATE *image_state) { 572ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis // Skip validation if this image was created through WSI 573e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis if (image_state->binding.mem != MEMTRACKER_SWAP_CHAIN_IMAGE_KEY) { 574ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis // First update CB binding in MemObj mini CB list 575d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis for (auto mem_binding : image_state->GetBoundMemory()) { 5769a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *pMemInfo = GetMemObjInfo(dev_data, mem_binding); 577d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis if (pMemInfo) { 578d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis pMemInfo->cb_bindings.insert(cb_node); 579d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis // Now update CBInfo's Mem reference list 580d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis cb_node->memObjs.insert(mem_binding); 581d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis } 582ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } 583f940225c9e5e3e14b3f5a32d3ea360b585614600Tobin Ehlis // Now update cb binding for image 5841facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis cb_node->object_bindings.insert({reinterpret_cast<uint64_t &>(image_state->image), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT}); 5851facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis image_state->cb_bindings.insert(cb_node); 586ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } 587ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis} 588ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis 58903ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis// Create binding link between given image view node and its image with command buffer node 59003ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlisvoid AddCommandBufferBindingImageView(const layer_data *dev_data, GLOBAL_CB_NODE *cb_node, IMAGE_VIEW_STATE *view_state) { 59103ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis // First add bindings for imageView 59203ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis view_state->cb_bindings.insert(cb_node); 59303ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis cb_node->object_bindings.insert( 59403ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis {reinterpret_cast<uint64_t &>(view_state->image_view), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT}); 5959a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_state = GetImageState(dev_data, view_state->create_info.image); 59603ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis // Add bindings for image within imageView 5971facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis if (image_state) { 5981facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis AddCommandBufferBindingImage(dev_data, cb_node, image_state); 59903ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis } 60003ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis} 60103ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis 602ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis// Create binding link between given buffer node and command buffer node 6035cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlisvoid AddCommandBufferBindingBuffer(const layer_data *dev_data, GLOBAL_CB_NODE *cb_node, BUFFER_STATE *buffer_state) { 604ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis // First update CB binding in MemObj mini CB list 6055cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis for (auto mem_binding : buffer_state->GetBoundMemory()) { 6069a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *pMemInfo = GetMemObjInfo(dev_data, mem_binding); 607d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis if (pMemInfo) { 608d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis pMemInfo->cb_bindings.insert(cb_node); 609d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis // Now update CBInfo's Mem reference list 610d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis cb_node->memObjs.insert(mem_binding); 611d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis } 612ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } 613ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis // Now update cb binding for buffer 6145cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis cb_node->object_bindings.insert({reinterpret_cast<uint64_t &>(buffer_state->buffer), VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT}); 6155cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis buffer_state->cb_bindings.insert(cb_node); 616ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis} 617ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis 61877b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis// Create binding link between given buffer view node and its buffer with command buffer node 61977b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlisvoid AddCommandBufferBindingBufferView(const layer_data *dev_data, GLOBAL_CB_NODE *cb_node, BUFFER_VIEW_STATE *view_state) { 62077b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis // First add bindings for bufferView 62177b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis view_state->cb_bindings.insert(cb_node); 62277b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis cb_node->object_bindings.insert( 62377b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis {reinterpret_cast<uint64_t &>(view_state->buffer_view), VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT}); 6249a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto buffer_state = GetBufferState(dev_data, view_state->create_info.buffer); 62577b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis // Add bindings for buffer within bufferView 6265cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis if (buffer_state) { 6275cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis AddCommandBufferBindingBuffer(dev_data, cb_node, buffer_state); 62877b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis } 62977b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis} 63077b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis 631400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis// For every mem obj bound to particular CB, free bindings related to that CB 632d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlisstatic void clear_cmd_buf_and_mem_references(layer_data *dev_data, GLOBAL_CB_NODE *cb_node) { 633d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis if (cb_node) { 634d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis if (cb_node->memObjs.size() > 0) { 635d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis for (auto mem : cb_node->memObjs) { 6369a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *pInfo = GetMemObjInfo(dev_data, mem); 6375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pInfo) { 638d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis pInfo->cb_bindings.erase(cb_node); 6395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 641d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis cb_node->memObjs.clear(); 6425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 643d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis cb_node->validate_functions.clear(); 6445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 646400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis// Overloaded call to above function when GLOBAL_CB_NODE has not already been looked-up 647400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlisstatic void clear_cmd_buf_and_mem_references(layer_data *dev_data, const VkCommandBuffer cb) { 6489a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis clear_cmd_buf_and_mem_references(dev_data, GetCBNode(dev_data, cb)); 6495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 6505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 651f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis// Clear a single object binding from given memory object, or report error if binding is missing 652f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlisstatic bool ClearMemoryObjectBinding(layer_data *dev_data, uint64_t handle, VkDebugReportObjectTypeEXT type, VkDeviceMemory mem) { 6539a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *mem_info = GetMemObjInfo(dev_data, mem); 654f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis // This obj is bound to a memory object. Remove the reference to this object in that memory object's list 655d4cd34fd49caa759cf01cafa5fa271401b17c3b9Jeremy Hayes if (mem_info) { 656d4cd34fd49caa759cf01cafa5fa271401b17c3b9Jeremy Hayes mem_info->obj_bindings.erase({handle, type}); 657f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis } 658f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis return false; 659f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis} 660f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis 661f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis// ClearMemoryObjectBindings clears the binding of objects to memory 662f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis// For the given object it pulls the memory bindings and makes sure that the bindings 663f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis// no longer refer to the object being cleared. This occurs when objects are destroyed. 6648c59133586421be878d393799b30044497f77727Mark Lobodzinskibool ClearMemoryObjectBindings(layer_data *dev_data, uint64_t handle, VkDebugReportObjectTypeEXT type) { 665f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis bool skip = false; 666f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis BINDABLE *mem_binding = GetObjectMemBinding(dev_data, handle, type); 667f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis if (mem_binding) { 668f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis if (!mem_binding->sparse) { 669f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis skip = ClearMemoryObjectBinding(dev_data, handle, type, mem_binding->binding.mem); 670cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else { // Sparse, clear all bindings 671bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski for (auto &sparse_mem_binding : mem_binding->sparse_bindings) { 672f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis skip |= ClearMemoryObjectBinding(dev_data, handle, type, sparse_mem_binding.mem); 6735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 676f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis return skip; 6775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 6785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 679888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis// For given mem object, verify that it is not null or UNBOUND, if it is, report error. Return skip value. 680888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlisbool VerifyBoundMemoryIsValid(const layer_data *dev_data, VkDeviceMemory mem, uint64_t handle, const char *api_name, 68135ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis const char *type_name, UNIQUE_VALIDATION_ERROR_CODE error_code) { 682888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis bool result = false; 683888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis if (VK_NULL_HANDLE == mem) { 684888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis result = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, handle, 685cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, error_code, "MEM", "%s: Vk%s object 0x%" PRIxLEAST64 686cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " used with no memory bound. Memory should be bound by calling " 687cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkBind%sMemory(). %s", 68835ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis api_name, type_name, handle, type_name, validation_error_map[error_code]); 689888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis } else if (MEMORY_UNBOUND == mem) { 690888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis result = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, handle, 691cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, error_code, "MEM", "%s: Vk%s object 0x%" PRIxLEAST64 692cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " used with no memory bound and previously bound memory was freed. " 693cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Memory must not be freed prior to this operation. %s", 69435ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis api_name, type_name, handle, validation_error_map[error_code]); 695888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis } 696888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis return result; 697888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis} 698888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis 699b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski// Check to see if memory was ever bound to this image 70035ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlisbool ValidateMemoryIsBoundToImage(const layer_data *dev_data, const IMAGE_STATE *image_state, const char *api_name, 70135ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis UNIQUE_VALIDATION_ERROR_CODE error_code) { 702b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski bool result = false; 7031facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis if (0 == (static_cast<uint32_t>(image_state->createInfo.flags) & VK_IMAGE_CREATE_SPARSE_BINDING_BIT)) { 70435ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis result = VerifyBoundMemoryIsValid(dev_data, image_state->binding.mem, 70535ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis reinterpret_cast<const uint64_t &>(image_state->image), api_name, "Image", error_code); 706b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski } 707b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski return result; 708b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski} 709b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski 710b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski// Check to see if memory was bound to this buffer 71135ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlisbool ValidateMemoryIsBoundToBuffer(const layer_data *dev_data, const BUFFER_STATE *buffer_state, const char *api_name, 71235ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis UNIQUE_VALIDATION_ERROR_CODE error_code) { 713b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski bool result = false; 7145cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis if (0 == (static_cast<uint32_t>(buffer_state->createInfo.flags) & VK_BUFFER_CREATE_SPARSE_BINDING_BIT)) { 7155cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis result = VerifyBoundMemoryIsValid(dev_data, buffer_state->binding.mem, 71635ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis reinterpret_cast<const uint64_t &>(buffer_state->buffer), api_name, "Buffer", error_code); 717b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski } 718b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski return result; 719b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski} 720b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski 7213a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// SetMemBinding is used to establish immutable, non-sparse binding between a single image/buffer object and memory object. 7223a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// Corresponding valid usage checks are in ValidateSetMemBinding(). 723c18f059542c30f6b37f8a654df020be38adfade6Cort Strattonstatic void SetMemBinding(layer_data *dev_data, VkDeviceMemory mem, uint64_t handle, VkDebugReportObjectTypeEXT type, 724888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis const char *apiName) { 725c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton if (mem != VK_NULL_HANDLE) { 726c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton BINDABLE *mem_binding = GetObjectMemBinding(dev_data, handle, type); 727c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton assert(mem_binding); 728c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton DEVICE_MEM_INFO *mem_info = GetMemObjInfo(dev_data, mem); 729c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton if (mem_info) { 730c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton mem_info->obj_bindings.insert({handle, type}); 731c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton // For image objects, make sure default memory state is correctly set 732c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton // TODO : What's the best/correct way to handle this? 733c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton if (VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT == type) { 734c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton auto const image_state = GetImageState(dev_data, VkImage(handle)); 735c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton if (image_state) { 736c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton VkImageCreateInfo ici = image_state->createInfo; 737c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton if (ici.usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) { 738c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton // TODO:: More memory state transition stuff. 739c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton } 740c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton } 741c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton } 742c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton mem_binding->binding.mem = mem; 743c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton } 744c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton } 745c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton} 7463a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton 7473a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// Valid usage checks for a call to SetMemBinding(). 7483a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// For NULL mem case, output warning 7493a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// Make sure given object is in global object map 7503a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// IF a previous binding existed, output validation error 7513a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// Otherwise, add reference from objectInfo to memoryInfo 7523a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// Add reference off of objInfo 7533a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// TODO: We may need to refactor or pass in multiple valid usage statements to handle multiple valid usage conditions. 754c18f059542c30f6b37f8a654df020be38adfade6Cort Strattonstatic bool ValidateSetMemBinding(layer_data *dev_data, VkDeviceMemory mem, uint64_t handle, VkDebugReportObjectTypeEXT type, 755c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton const char *apiName) { 75683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 757f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis // It's an error to bind an object to NULL memory 758d3876b4ff7c293a14f73fe3622513d1fa91bf2d0Jeremy Hayes if (mem != VK_NULL_HANDLE) { 759f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis BINDABLE *mem_binding = GetObjectMemBinding(dev_data, handle, type); 760888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis assert(mem_binding); 76110ffe2d353eaff714ed92a2835af77d8b5042d31Cort if (mem_binding->sparse) { 76210ffe2d353eaff714ed92a2835af77d8b5042d31Cort UNIQUE_VALIDATION_ERROR_CODE error_code = VALIDATION_ERROR_00804; 76310ffe2d353eaff714ed92a2835af77d8b5042d31Cort const char *handle_type = "IMAGE"; 76474300755ed9ec780d6073af71e47f201217008d6Cort Stratton if (strcmp(apiName, "vkBindBufferMemory()") == 0) { 76510ffe2d353eaff714ed92a2835af77d8b5042d31Cort error_code = VALIDATION_ERROR_00792; 76610ffe2d353eaff714ed92a2835af77d8b5042d31Cort handle_type = "BUFFER"; 76710ffe2d353eaff714ed92a2835af77d8b5042d31Cort } else { 76874300755ed9ec780d6073af71e47f201217008d6Cort Stratton assert(strcmp(apiName, "vkBindImageMemory()") == 0); 76910ffe2d353eaff714ed92a2835af77d8b5042d31Cort } 77010ffe2d353eaff714ed92a2835af77d8b5042d31Cort skip_call |= 77110ffe2d353eaff714ed92a2835af77d8b5042d31Cort log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 77210ffe2d353eaff714ed92a2835af77d8b5042d31Cort reinterpret_cast<uint64_t &>(mem), __LINE__, error_code, "MEM", 77310ffe2d353eaff714ed92a2835af77d8b5042d31Cort "In %s, attempting to bind memory (0x%" PRIxLEAST64 ") to object (0x%" PRIxLEAST64 77410ffe2d353eaff714ed92a2835af77d8b5042d31Cort ") which was created with sparse memory flags (VK_%s_CREATE_SPARSE_*_BIT). %s", 77510ffe2d353eaff714ed92a2835af77d8b5042d31Cort apiName, reinterpret_cast<uint64_t &>(mem), handle, handle_type, validation_error_map[error_code]); 77610ffe2d353eaff714ed92a2835af77d8b5042d31Cort } 7779a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *mem_info = GetMemObjInfo(dev_data, mem); 778888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis if (mem_info) { 7799a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *prev_binding = GetMemObjInfo(dev_data, mem_binding->binding.mem); 780888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis if (prev_binding) { 78198c2a17e1a549df84f4239f619bc0955f632cb43Cort UNIQUE_VALIDATION_ERROR_CODE error_code = VALIDATION_ERROR_00803; 78274300755ed9ec780d6073af71e47f201217008d6Cort Stratton if (strcmp(apiName, "vkBindBufferMemory()") == 0) { 78398c2a17e1a549df84f4239f619bc0955f632cb43Cort error_code = VALIDATION_ERROR_00791; 78498c2a17e1a549df84f4239f619bc0955f632cb43Cort } else { 78574300755ed9ec780d6073af71e47f201217008d6Cort Stratton assert(strcmp(apiName, "vkBindImageMemory()") == 0); 78698c2a17e1a549df84f4239f619bc0955f632cb43Cort } 787888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis skip_call |= 788888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 78998c2a17e1a549df84f4239f619bc0955f632cb43Cort reinterpret_cast<uint64_t &>(mem), __LINE__, error_code, "MEM", 790888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis "In %s, attempting to bind memory (0x%" PRIxLEAST64 ") to object (0x%" PRIxLEAST64 79198c2a17e1a549df84f4239f619bc0955f632cb43Cort ") which has already been bound to mem object 0x%" PRIxLEAST64 ". %s", 79298c2a17e1a549df84f4239f619bc0955f632cb43Cort apiName, reinterpret_cast<uint64_t &>(mem), handle, reinterpret_cast<uint64_t &>(prev_binding->mem), 79398c2a17e1a549df84f4239f619bc0955f632cb43Cort validation_error_map[error_code]); 794f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis } else if (mem_binding->binding.mem == MEMORY_UNBOUND) { 795888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis skip_call |= 796888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 797888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis reinterpret_cast<uint64_t &>(mem), __LINE__, MEMTRACK_REBIND_OBJECT, "MEM", 798888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis "In %s, attempting to bind memory (0x%" PRIxLEAST64 ") to object (0x%" PRIxLEAST64 799888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis ") which was previous bound to memory that has since been freed. Memory bindings are immutable in " 800888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis "Vulkan so this attempt to bind to new memory is not allowed.", 801888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis apiName, reinterpret_cast<uint64_t &>(mem), handle); 8025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 80583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis return skip_call; 8065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 8075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// For NULL mem case, clear any previous binding Else... 8095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Make sure given object is in its object map 8105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// IF a previous binding existed, update binding 8115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Add reference from objectInfo to memoryInfo 8125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Add reference off of object's binding info 8130a1ce3dfd81c9f4efbe46f5ba5ddaea70bc4aa61Chris Forbes// Return VK_TRUE if addition is successful, VK_FALSE otherwise 814f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlisstatic bool SetSparseMemBinding(layer_data *dev_data, MEM_BINDING binding, uint64_t handle, VkDebugReportObjectTypeEXT type, 815f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis const char *apiName) { 81683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = VK_FALSE; 8175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Handle NULL case separately, just clear previous binding & decrement reference 818f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis if (binding.mem == VK_NULL_HANDLE) { 819f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis // TODO : This should cause the range of the resource to be unbound according to spec 8205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 821f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis BINDABLE *mem_binding = GetObjectMemBinding(dev_data, handle, type); 822f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis assert(mem_binding); 823f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis assert(mem_binding->sparse); 8249a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *mem_info = GetMemObjInfo(dev_data, binding.mem); 825f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis if (mem_info) { 826f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis mem_info->obj_bindings.insert({handle, type}); 8272e415b757c1e43fda35311aad026af8d5c96681cTobin Ehlis // Need to set mem binding for this object 828f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis mem_binding->sparse_bindings.insert(binding); 8295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 83183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis return skip_call; 832caf05e0db4959ae196ab34b024f352d9c0326870Tobin Ehlis} 833caf05e0db4959ae196ab34b024f352d9c0326870Tobin Ehlis 8345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Return a string representation of CMD_TYPE enum 8355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic string cmdTypeToString(CMD_TYPE cmd) { 8365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis switch (cmd) { 837cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_BINDPIPELINE: 838cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_BINDPIPELINE"; 839cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_BINDPIPELINEDELTA: 840cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_BINDPIPELINEDELTA"; 841cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETVIEWPORTSTATE: 842cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_SETVIEWPORTSTATE"; 843cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETLINEWIDTHSTATE: 844cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_SETLINEWIDTHSTATE"; 845cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETDEPTHBIASSTATE: 846cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_SETDEPTHBIASSTATE"; 847cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETBLENDSTATE: 848cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_SETBLENDSTATE"; 849cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETDEPTHBOUNDSSTATE: 850cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_SETDEPTHBOUNDSSTATE"; 851cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETSTENCILREADMASKSTATE: 852cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_SETSTENCILREADMASKSTATE"; 853cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETSTENCILWRITEMASKSTATE: 854cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_SETSTENCILWRITEMASKSTATE"; 855cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETSTENCILREFERENCESTATE: 856cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_SETSTENCILREFERENCESTATE"; 857cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_BINDDESCRIPTORSETS: 858cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_BINDDESCRIPTORSETS"; 859cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_BINDINDEXBUFFER: 860cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_BINDINDEXBUFFER"; 861cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_BINDVERTEXBUFFER: 862cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_BINDVERTEXBUFFER"; 863cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_DRAW: 864cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_DRAW"; 865cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_DRAWINDEXED: 866cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_DRAWINDEXED"; 867cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_DRAWINDIRECT: 868cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_DRAWINDIRECT"; 869cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_DRAWINDEXEDINDIRECT: 870cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_DRAWINDEXEDINDIRECT"; 871cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_DISPATCH: 872cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_DISPATCH"; 873cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_DISPATCHINDIRECT: 874cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_DISPATCHINDIRECT"; 875cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_COPYBUFFER: 876cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_COPYBUFFER"; 877cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_COPYIMAGE: 878cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_COPYIMAGE"; 879cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_BLITIMAGE: 880cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_BLITIMAGE"; 881cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_COPYBUFFERTOIMAGE: 882cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_COPYBUFFERTOIMAGE"; 883cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_COPYIMAGETOBUFFER: 884cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_COPYIMAGETOBUFFER"; 885cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_CLONEIMAGEDATA: 886cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_CLONEIMAGEDATA"; 887cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_UPDATEBUFFER: 888cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_UPDATEBUFFER"; 889cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_FILLBUFFER: 890cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_FILLBUFFER"; 891cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_CLEARCOLORIMAGE: 892cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_CLEARCOLORIMAGE"; 893cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_CLEARATTACHMENTS: 894cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_CLEARCOLORATTACHMENT"; 895cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_CLEARDEPTHSTENCILIMAGE: 896cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_CLEARDEPTHSTENCILIMAGE"; 897cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_RESOLVEIMAGE: 898cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_RESOLVEIMAGE"; 899cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SETEVENT: 900cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_SETEVENT"; 901cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_RESETEVENT: 902cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_RESETEVENT"; 903cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_WAITEVENTS: 904cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_WAITEVENTS"; 905cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_PIPELINEBARRIER: 906cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_PIPELINEBARRIER"; 907cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_BEGINQUERY: 908cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_BEGINQUERY"; 909cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_ENDQUERY: 910cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_ENDQUERY"; 911cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_RESETQUERYPOOL: 912cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_RESETQUERYPOOL"; 913cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_COPYQUERYPOOLRESULTS: 914cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_COPYQUERYPOOLRESULTS"; 915cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_WRITETIMESTAMP: 916cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_WRITETIMESTAMP"; 917cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_INITATOMICCOUNTERS: 918cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_INITATOMICCOUNTERS"; 919cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_LOADATOMICCOUNTERS: 920cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_LOADATOMICCOUNTERS"; 921cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_SAVEATOMICCOUNTERS: 922cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_SAVEATOMICCOUNTERS"; 923cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_BEGINRENDERPASS: 924cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_BEGINRENDERPASS"; 925cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case CMD_ENDRENDERPASS: 926cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "CMD_ENDRENDERPASS"; 927cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 928cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "UNKNOWN"; 9295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 9315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// SPIRV utility functions 9335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic void build_def_index(shader_module *module) { 9345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto insn : *module) { 9355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis switch (insn.opcode()) { 936cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Types 937cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeVoid: 938cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeBool: 939cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeInt: 940cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeFloat: 941cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeVector: 942cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeMatrix: 943cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeImage: 944cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeSampler: 945cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeSampledImage: 946cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeArray: 947cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeRuntimeArray: 948cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeStruct: 949cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeOpaque: 950cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypePointer: 951cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeFunction: 952cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeEvent: 953cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeDeviceEvent: 954cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeReserveId: 955cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeQueue: 956cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypePipe: 957cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski module->def_index[insn.word(1)] = insn.offset(); 958cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 9595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 960cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Fixed constants 961cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpConstantTrue: 962cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpConstantFalse: 963cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpConstant: 964cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpConstantComposite: 965cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpConstantSampler: 966cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpConstantNull: 967cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski module->def_index[insn.word(2)] = insn.offset(); 968cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 9695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 970cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Specialization constants 971cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpSpecConstantTrue: 972cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpSpecConstantFalse: 973cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpSpecConstant: 974cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpSpecConstantComposite: 975cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpSpecConstantOp: 976cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski module->def_index[insn.word(2)] = insn.offset(); 977cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 9785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 979cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Variables 980cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpVariable: 981cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski module->def_index[insn.word(2)] = insn.offset(); 982cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 9835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 984cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Functions 985cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpFunction: 986cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski module->def_index[insn.word(2)] = insn.offset(); 987cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 9885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 989cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 990cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // We don't care about any other defs for now. 991cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 9925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 9955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic spirv_inst_iter find_entrypoint(shader_module *src, char const *name, VkShaderStageFlagBits stageBits) { 9975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto insn : *src) { 9985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.opcode() == spv::OpEntryPoint) { 9995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto entrypointName = (char const *)&insn.word(3); 10005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto entrypointStageBits = 1u << insn.word(1); 10015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!strcmp(entrypointName, name) && (entrypointStageBits & stageBits)) { 10035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return insn; 10045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 10055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 10065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 10075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return src->end(); 10095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 10105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic char const *storage_class_name(unsigned sc) { 10125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis switch (sc) { 1013cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassInput: 1014cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "input"; 1015cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassOutput: 1016cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "output"; 1017cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassUniformConstant: 1018cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "const uniform"; 1019cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassUniform: 1020cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "uniform"; 1021cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassWorkgroup: 1022cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "workgroup local"; 1023cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassCrossWorkgroup: 1024cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "workgroup global"; 1025cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassPrivate: 1026cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "private global"; 1027cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassFunction: 1028cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "function"; 1029cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassGeneric: 1030cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "generic"; 1031cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassAtomicCounter: 1032cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "atomic counter"; 1033cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassImage: 1034cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "image"; 1035cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassPushConstant: 1036cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "push constant"; 1037cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 1038cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "unknown"; 10395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 10405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 10415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 104225002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// Get the value of an integral constant 10435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisunsigned get_constant_value(shader_module const *src, unsigned id) { 10445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto value = src->get_def(id); 10455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(value != src->end()); 10465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (value.opcode() != spv::OpConstant) { 104825002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // TODO: Either ensure that the specialization transform is already performed on a module we're 104925002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // considering here, OR -- specialize on the fly now. 10505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return 1; 10515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 10525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return value.word(3); 10545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 10555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10569ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbesstatic void describe_type_inner(std::ostringstream &ss, shader_module const *src, unsigned type) { 10575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto insn = src->get_def(type); 10585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(insn != src->end()); 10595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis switch (insn.opcode()) { 1061cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeBool: 1062cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << "bool"; 1063cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1064cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeInt: 1065cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << (insn.word(3) ? 's' : 'u') << "int" << insn.word(2); 1066cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1067cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeFloat: 1068cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << "float" << insn.word(2); 1069cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1070cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeVector: 1071cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << "vec" << insn.word(3) << " of "; 1072cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski describe_type_inner(ss, src, insn.word(2)); 1073cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1074cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeMatrix: 1075cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << "mat" << insn.word(3) << " of "; 1076cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski describe_type_inner(ss, src, insn.word(2)); 1077cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1078cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeArray: 1079cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << "arr[" << get_constant_value(src, insn.word(3)) << "] of "; 1080cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski describe_type_inner(ss, src, insn.word(2)); 1081cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1082cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypePointer: 1083cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << "ptr to " << storage_class_name(insn.word(2)) << " "; 1084cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski describe_type_inner(ss, src, insn.word(3)); 1085cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1086cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeStruct: { 1087cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << "struct of ("; 1088cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski for (unsigned i = 2; i < insn.len(); i++) { 1089cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski describe_type_inner(ss, src, insn.word(i)); 1090cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (i == insn.len() - 1) { 1091cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << ")"; 1092cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else { 1093cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << ", "; 1094cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 10959ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes } 1096cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 10975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 1098cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeSampler: 1099cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << "sampler"; 1100cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1101cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeSampledImage: 1102cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << "sampler+"; 1103cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski describe_type_inner(ss, src, insn.word(2)); 1104cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1105cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeImage: 1106cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << "image(dim=" << insn.word(3) << ", sampled=" << insn.word(7) << ")"; 1107cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1108cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 1109cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << "oddtype"; 1110cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 11115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 11125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 11135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 11149ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbesstatic std::string describe_type(shader_module const *src, unsigned type) { 11159ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes std::ostringstream ss; 11169ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes describe_type_inner(ss, src, type); 11179ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes return ss.str(); 11189ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes} 11199ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes 1120bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic bool is_narrow_numeric_type(spirv_inst_iter type) { 1121cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (type.opcode() != spv::OpTypeInt && type.opcode() != spv::OpTypeFloat) return false; 112237576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes return type.word(2) < 64; 112337576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes} 112437576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes 1125bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic bool types_match(shader_module const *a, shader_module const *b, unsigned a_type, unsigned b_type, bool a_arrayed, 1126bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski bool b_arrayed, bool relaxed) { 112725002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Walk two type trees together, and complain about differences 11285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto a_insn = a->get_def(a_type); 11295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto b_insn = b->get_def(b_type); 11305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(a_insn != a->end()); 11315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(b_insn != b->end()); 11325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 11337c755c8aca6857046df9516d8336416165969cb9Chris Forbes if (a_arrayed && a_insn.opcode() == spv::OpTypeArray) { 113437576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes return types_match(a, b, a_insn.word(2), b_type, false, b_arrayed, relaxed); 11357c755c8aca6857046df9516d8336416165969cb9Chris Forbes } 11367c755c8aca6857046df9516d8336416165969cb9Chris Forbes 11375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (b_arrayed && b_insn.opcode() == spv::OpTypeArray) { 113825002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // We probably just found the extra level of arrayness in b_type: compare the type inside it to a_type 113937576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes return types_match(a, b, a_type, b_insn.word(2), a_arrayed, false, relaxed); 114037576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes } 114137576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes 114237576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes if (a_insn.opcode() == spv::OpTypeVector && relaxed && is_narrow_numeric_type(b_insn)) { 114337576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes return types_match(a, b, a_insn.word(2), b_type, a_arrayed, b_arrayed, false); 11445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 11455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 11465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (a_insn.opcode() != b_insn.opcode()) { 11475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 11485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 11495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 11507c755c8aca6857046df9516d8336416165969cb9Chris Forbes if (a_insn.opcode() == spv::OpTypePointer) { 115125002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Match on pointee type. storage class is expected to differ 115237576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes return types_match(a, b, a_insn.word(3), b_insn.word(3), a_arrayed, b_arrayed, relaxed); 11537c755c8aca6857046df9516d8336416165969cb9Chris Forbes } 11547c755c8aca6857046df9516d8336416165969cb9Chris Forbes 11557c755c8aca6857046df9516d8336416165969cb9Chris Forbes if (a_arrayed || b_arrayed) { 115625002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // If we havent resolved array-of-verts by here, we're not going to. 11577c755c8aca6857046df9516d8336416165969cb9Chris Forbes return false; 11587c755c8aca6857046df9516d8336416165969cb9Chris Forbes } 11597c755c8aca6857046df9516d8336416165969cb9Chris Forbes 11605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis switch (a_insn.opcode()) { 1161cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeBool: 1162cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return true; 1163cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeInt: 1164cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Match on width, signedness 1165cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return a_insn.word(2) == b_insn.word(2) && a_insn.word(3) == b_insn.word(3); 1166cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeFloat: 1167cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Match on width 1168cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return a_insn.word(2) == b_insn.word(2); 1169cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeVector: 1170cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Match on element type, count. 1171cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!types_match(a, b, a_insn.word(2), b_insn.word(2), a_arrayed, b_arrayed, false)) return false; 1172cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (relaxed && is_narrow_numeric_type(a->get_def(a_insn.word(2)))) { 1173cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return a_insn.word(3) >= b_insn.word(3); 1174cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else { 1175cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return a_insn.word(3) == b_insn.word(3); 11765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 1177cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeMatrix: 1178cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Match on element type, count. 1179cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return types_match(a, b, a_insn.word(2), b_insn.word(2), a_arrayed, b_arrayed, false) && 1180cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski a_insn.word(3) == b_insn.word(3); 1181cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeArray: 1182cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Match on element type, count. these all have the same layout. we don't get here if b_arrayed. This differs from 1183cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // vector & matrix types in that the array size is the id of a constant instruction, * not a literal within OpTypeArray 1184cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return types_match(a, b, a_insn.word(2), b_insn.word(2), a_arrayed, b_arrayed, false) && 1185cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski get_constant_value(a, a_insn.word(3)) == get_constant_value(b, b_insn.word(3)); 1186cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeStruct: 1187cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Match on all element types 1188cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski { 1189cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (a_insn.len() != b_insn.len()) { 1190cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return false; // Structs cannot match if member counts differ 1191cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 11925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1193cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski for (unsigned i = 2; i < a_insn.len(); i++) { 1194cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!types_match(a, b, a_insn.word(i), b_insn.word(i), a_arrayed, b_arrayed, false)) { 1195cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return false; 1196cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 1197cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 1198cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski 1199cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return true; 1200cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 1201cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 1202cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Remaining types are CLisms, or may not appear in the interfaces we are interested in. Just claim no match. 1203cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return false; 12045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 12055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 12065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 12075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic int value_or_default(std::unordered_map<unsigned, unsigned> const &map, unsigned id, int def) { 12085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto it = map.find(id); 12095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (it == map.end()) 12105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return def; 12115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis else 12125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return it->second; 12135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 12145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 12155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic unsigned get_locations_consumed_by_type(shader_module const *src, unsigned type, bool strip_array_level) { 12165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto insn = src->get_def(type); 12175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(insn != src->end()); 12185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 12195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis switch (insn.opcode()) { 1220cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypePointer: 1221cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // See through the ptr -- this is only ever at the toplevel for graphics shaders we're never actually passing 1222cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // pointers around. 1223cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return get_locations_consumed_by_type(src, insn.word(3), strip_array_level); 1224cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeArray: 1225cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (strip_array_level) { 1226cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return get_locations_consumed_by_type(src, insn.word(2), false); 1227cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else { 1228cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return get_constant_value(src, insn.word(3)) * get_locations_consumed_by_type(src, insn.word(2), false); 1229cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 1230cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeMatrix: 1231cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Num locations is the dimension * element size 1232cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return insn.word(3) * get_locations_consumed_by_type(src, insn.word(2), false); 1233cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeVector: { 1234cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski auto scalar_type = src->get_def(insn.word(2)); 1235cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski auto bit_width = 1236cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski (scalar_type.opcode() == spv::OpTypeInt || scalar_type.opcode() == spv::OpTypeFloat) ? scalar_type.word(2) : 32; 1237cc52143fc093e1e62d2dacc4abc3966e04b6f6d6Chris Forbes 1238cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Locations are 128-bit wide; 3- and 4-component vectors of 64 bit types require two. 1239cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return (bit_width * insn.word(3) + 127) / 128; 1240cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 1241cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 1242cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Everything else is just 1. 1243cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return 1; 12445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1245cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // TODO: extend to handle 64bit scalar types, whose vectors may need multiple locations. 12465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 12475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 12485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1249c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbesstatic unsigned get_locations_consumed_by_format(VkFormat format) { 1250c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes switch (format) { 1251cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64G64B64A64_SFLOAT: 1252cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64G64B64A64_SINT: 1253cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64G64B64A64_UINT: 1254cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64G64B64_SFLOAT: 1255cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64G64B64_SINT: 1256cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64G64B64_UINT: 1257cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return 2; 1258cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 1259cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return 1; 1260c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes } 1261c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes} 1262c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes 12635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlistypedef std::pair<unsigned, unsigned> location_t; 12645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlistypedef std::pair<unsigned, unsigned> descriptor_slot_t; 12655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 12665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstruct interface_var { 12675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t id; 12685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t type_id; 12695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t offset; 1270b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes bool is_patch; 1271fff9393206f66a154438e16fa0562c989f425498Chris Forbes bool is_block_member; 1272b0436668e6594b8528e96de7bed208399fb2431dChris Forbes bool is_relaxed_precision; 127325002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // TODO: collect the name, too? Isn't required to be present. 12745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}; 12755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1276031261d21af8907953dd763398ce9a23e65b8749Chris Forbesstruct shader_stage_attributes { 1277031261d21af8907953dd763398ce9a23e65b8749Chris Forbes char const *const name; 1278031261d21af8907953dd763398ce9a23e65b8749Chris Forbes bool arrayed_input; 1279031261d21af8907953dd763398ce9a23e65b8749Chris Forbes bool arrayed_output; 1280031261d21af8907953dd763398ce9a23e65b8749Chris Forbes}; 1281031261d21af8907953dd763398ce9a23e65b8749Chris Forbes 1282031261d21af8907953dd763398ce9a23e65b8749Chris Forbesstatic shader_stage_attributes shader_stage_attribs[] = { 1283bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vertex shader", false, false}, {"tessellation control shader", true, true}, {"tessellation evaluation shader", true, false}, 1284bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"geometry shader", true, false}, {"fragment shader", false, false}, 1285031261d21af8907953dd763398ce9a23e65b8749Chris Forbes}; 1286031261d21af8907953dd763398ce9a23e65b8749Chris Forbes 12875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic spirv_inst_iter get_struct_type(shader_module const *src, spirv_inst_iter def, bool is_array_of_verts) { 12885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis while (true) { 12895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (def.opcode() == spv::OpTypePointer) { 12905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis def = src->get_def(def.word(3)); 12915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (def.opcode() == spv::OpTypeArray && is_array_of_verts) { 12925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis def = src->get_def(def.word(2)); 12935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis is_array_of_verts = false; 12945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (def.opcode() == spv::OpTypeStruct) { 12955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return def; 12965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 12975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return src->end(); 12985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 12995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 13015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1302bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic void collect_interface_block_members(shader_module const *src, std::map<location_t, interface_var> *out, 13035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_map<unsigned, unsigned> const &blocks, bool is_array_of_verts, 1304b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes uint32_t id, uint32_t type_id, bool is_patch) { 130525002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Walk down the type_id presented, trying to determine whether it's actually an interface block. 1306031261d21af8907953dd763398ce9a23e65b8749Chris Forbes auto type = get_struct_type(src, src->get_def(type_id), is_array_of_verts && !is_patch); 13075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (type == src->end() || blocks.find(type.word(1)) == blocks.end()) { 130825002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // This isn't an interface block. 13095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return; 13105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 13125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_map<unsigned, unsigned> member_components; 13135b9f2047984d6ca10d89a35ba8a2ebe0fa6bff69Chris Forbes std::unordered_map<unsigned, unsigned> member_relaxed_precision; 13145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 131525002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Walk all the OpMemberDecorate for type's result id -- first pass, collect components. 13165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto insn : *src) { 13175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.opcode() == spv::OpMemberDecorate && insn.word(1) == type.word(1)) { 13185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned member_index = insn.word(2); 13195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 13205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.word(3) == spv::DecorationComponent) { 13215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned component = insn.word(4); 13225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis member_components[member_index] = component; 13235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13245b9f2047984d6ca10d89a35ba8a2ebe0fa6bff69Chris Forbes 13255b9f2047984d6ca10d89a35ba8a2ebe0fa6bff69Chris Forbes if (insn.word(3) == spv::DecorationRelaxedPrecision) { 13265b9f2047984d6ca10d89a35ba8a2ebe0fa6bff69Chris Forbes member_relaxed_precision[member_index] = 1; 13275b9f2047984d6ca10d89a35ba8a2ebe0fa6bff69Chris Forbes } 13285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 133125002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Second pass -- produce the output, from Location decorations 13325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto insn : *src) { 13335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.opcode() == spv::OpMemberDecorate && insn.word(1) == type.word(1)) { 13345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned member_index = insn.word(2); 13355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned member_type_id = type.word(2 + member_index); 13365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 13375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.word(3) == spv::DecorationLocation) { 13385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned location = insn.word(4); 13395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned num_locations = get_locations_consumed_by_type(src, member_type_id, false); 13405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto component_it = member_components.find(member_index); 13415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned component = component_it == member_components.end() ? 0 : component_it->second; 13425b9f2047984d6ca10d89a35ba8a2ebe0fa6bff69Chris Forbes bool is_relaxed_precision = member_relaxed_precision.find(member_index) != member_relaxed_precision.end(); 13435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 13445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (unsigned int offset = 0; offset < num_locations; offset++) { 1345b0436668e6594b8528e96de7bed208399fb2431dChris Forbes interface_var v = {}; 13465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis v.id = id; 134725002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // TODO: member index in interface_var too? 13485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis v.type_id = member_type_id; 13495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis v.offset = offset; 1350b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes v.is_patch = is_patch; 1351fff9393206f66a154438e16fa0562c989f425498Chris Forbes v.is_block_member = true; 13525b9f2047984d6ca10d89a35ba8a2ebe0fa6bff69Chris Forbes v.is_relaxed_precision = is_relaxed_precision; 13533a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes (*out)[std::make_pair(location + offset, component)] = v; 13545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 13595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1360bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic std::map<location_t, interface_var> collect_interface_by_location(shader_module const *src, spirv_inst_iter entrypoint, 1361bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski spv::StorageClass sinterface, bool is_array_of_verts) { 13625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_map<unsigned, unsigned> var_locations; 13635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_map<unsigned, unsigned> var_builtins; 13645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_map<unsigned, unsigned> var_components; 13655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_map<unsigned, unsigned> blocks; 1366b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes std::unordered_map<unsigned, unsigned> var_patch; 1367b0436668e6594b8528e96de7bed208399fb2431dChris Forbes std::unordered_map<unsigned, unsigned> var_relaxed_precision; 13685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 13695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto insn : *src) { 137025002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // We consider two interface models: SSO rendezvous-by-location, and builtins. Complain about anything that 137125002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // fits neither model. 13725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.opcode() == spv::OpDecorate) { 13735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.word(2) == spv::DecorationLocation) { 13745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis var_locations[insn.word(1)] = insn.word(3); 13755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 13775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.word(2) == spv::DecorationBuiltIn) { 13785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis var_builtins[insn.word(1)] = insn.word(3); 13795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 13815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.word(2) == spv::DecorationComponent) { 13825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis var_components[insn.word(1)] = insn.word(3); 13835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 13855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.word(2) == spv::DecorationBlock) { 13865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis blocks[insn.word(1)] = 1; 13875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 1388b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes 1389b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes if (insn.word(2) == spv::DecorationPatch) { 1390b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes var_patch[insn.word(1)] = 1; 1391b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes } 1392b0436668e6594b8528e96de7bed208399fb2431dChris Forbes 1393b0436668e6594b8528e96de7bed208399fb2431dChris Forbes if (insn.word(2) == spv::DecorationRelaxedPrecision) { 1394b0436668e6594b8528e96de7bed208399fb2431dChris Forbes var_relaxed_precision[insn.word(1)] = 1; 1395b0436668e6594b8528e96de7bed208399fb2431dChris Forbes } 13965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 139925002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // TODO: handle grouped decorations 140025002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // TODO: handle index=1 dual source outputs from FS -- two vars will have the same location, and we DON'T want to clobber. 14015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 140225002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Find the end of the entrypoint's name string. additional zero bytes follow the actual null terminator, to fill out the 140325002b75574f762c62b1a00a595bab04ebb25452Mark 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. 1404c15b801a6e1a5dd5eed09e689aecdde7c4a90a5bMichael Mc Donnell uint32_t word = 3; 14055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis while (entrypoint.word(word) & 0xff000000u) { 14065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis ++word; 14075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 14085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis ++word; 14095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 14103a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes std::map<location_t, interface_var> out; 14113a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes 14125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (; word < entrypoint.len(); word++) { 14135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto insn = src->get_def(entrypoint.word(word)); 14145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(insn != src->end()); 14155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(insn.opcode() == spv::OpVariable); 14165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 14171d5109d5e0dcc530b27e632e73e1be5e12a28dcdJamie Madill if (insn.word(3) == static_cast<uint32_t>(sinterface)) { 14185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned id = insn.word(2); 14195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned type = insn.word(1); 14205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 14215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis int location = value_or_default(var_locations, id, -1); 14225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis int builtin = value_or_default(var_builtins, id, -1); 1423cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski unsigned component = value_or_default(var_components, id, 0); // Unspecified is OK, is 0 1424b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes bool is_patch = var_patch.find(id) != var_patch.end(); 1425b0436668e6594b8528e96de7bed208399fb2431dChris Forbes bool is_relaxed_precision = var_relaxed_precision.find(id) != var_relaxed_precision.end(); 14265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 142725002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // All variables and interface block members in the Input or Output storage classes must be decorated with either 142825002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // a builtin or an explicit location. 142925002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // 143025002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // TODO: integrate the interface block support here. For now, don't complain -- a valid SPIRV module will only hit 143125002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // this path for the interface block case, as the individual members of the type are decorated, rather than 143225002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // variable declarations. 14335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 14345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (location != -1) { 143525002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // A user-defined interface variable, with a location. Where a variable occupied multiple locations, emit 143625002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // one result for each. 14377c755c8aca6857046df9516d8336416165969cb9Chris Forbes unsigned num_locations = get_locations_consumed_by_type(src, type, is_array_of_verts && !is_patch); 14385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (unsigned int offset = 0; offset < num_locations; offset++) { 1439b0436668e6594b8528e96de7bed208399fb2431dChris Forbes interface_var v = {}; 14405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis v.id = id; 14415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis v.type_id = type; 14425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis v.offset = offset; 1443b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes v.is_patch = is_patch; 1444b0436668e6594b8528e96de7bed208399fb2431dChris Forbes v.is_relaxed_precision = is_relaxed_precision; 14455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis out[std::make_pair(location + offset, component)] = v; 14465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 14475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (builtin == -1) { 144825002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // An interface block instance 14493a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes collect_interface_block_members(src, &out, blocks, is_array_of_verts, id, type, is_patch); 14505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 14515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 14525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 14533a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes 14543a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes return out; 14555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 14565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1457cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskistatic std::vector<std::pair<uint32_t, interface_var>> collect_interface_by_input_attachment_index( 1458cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski debug_report_data *report_data, shader_module const *src, std::unordered_set<uint32_t> const &accessible_ids) { 14593a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes std::vector<std::pair<uint32_t, interface_var>> out; 1460745d49409296f060402b57950384caadb636a2b2Chris Forbes 1461745d49409296f060402b57950384caadb636a2b2Chris Forbes for (auto insn : *src) { 1462745d49409296f060402b57950384caadb636a2b2Chris Forbes if (insn.opcode() == spv::OpDecorate) { 1463745d49409296f060402b57950384caadb636a2b2Chris Forbes if (insn.word(2) == spv::DecorationInputAttachmentIndex) { 1464745d49409296f060402b57950384caadb636a2b2Chris Forbes auto attachment_index = insn.word(3); 1465745d49409296f060402b57950384caadb636a2b2Chris Forbes auto id = insn.word(1); 1466745d49409296f060402b57950384caadb636a2b2Chris Forbes 1467745d49409296f060402b57950384caadb636a2b2Chris Forbes if (accessible_ids.count(id)) { 1468745d49409296f060402b57950384caadb636a2b2Chris Forbes auto def = src->get_def(id); 1469745d49409296f060402b57950384caadb636a2b2Chris Forbes assert(def != src->end()); 1470745d49409296f060402b57950384caadb636a2b2Chris Forbes 1471745d49409296f060402b57950384caadb636a2b2Chris Forbes if (def.opcode() == spv::OpVariable && insn.word(3) == spv::StorageClassUniformConstant) { 1472e0cc9b3441a24e4fbd2b4e0a9d163dab2140264aChris Forbes auto num_locations = get_locations_consumed_by_type(src, def.word(1), false); 1473e0cc9b3441a24e4fbd2b4e0a9d163dab2140264aChris Forbes for (unsigned int offset = 0; offset < num_locations; offset++) { 1474b0436668e6594b8528e96de7bed208399fb2431dChris Forbes interface_var v = {}; 1475e0cc9b3441a24e4fbd2b4e0a9d163dab2140264aChris Forbes v.id = id; 1476e0cc9b3441a24e4fbd2b4e0a9d163dab2140264aChris Forbes v.type_id = def.word(1); 1477e0cc9b3441a24e4fbd2b4e0a9d163dab2140264aChris Forbes v.offset = offset; 1478e0cc9b3441a24e4fbd2b4e0a9d163dab2140264aChris Forbes out.emplace_back(attachment_index + offset, v); 1479e0cc9b3441a24e4fbd2b4e0a9d163dab2140264aChris Forbes } 1480745d49409296f060402b57950384caadb636a2b2Chris Forbes } 1481745d49409296f060402b57950384caadb636a2b2Chris Forbes } 1482745d49409296f060402b57950384caadb636a2b2Chris Forbes } 1483745d49409296f060402b57950384caadb636a2b2Chris Forbes } 1484745d49409296f060402b57950384caadb636a2b2Chris Forbes } 14853a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes 14863a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes return out; 1487745d49409296f060402b57950384caadb636a2b2Chris Forbes} 1488745d49409296f060402b57950384caadb636a2b2Chris Forbes 1489cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskistatic std::vector<std::pair<descriptor_slot_t, interface_var>> collect_interface_by_descriptor_slot( 1490cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski debug_report_data *report_data, shader_module const *src, std::unordered_set<uint32_t> const &accessible_ids) { 14915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_map<unsigned, unsigned> var_sets; 14925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_map<unsigned, unsigned> var_bindings; 14935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 14945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto insn : *src) { 149525002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // All variables in the Uniform or UniformConstant storage classes are required to be decorated with both 149625002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // DecorationDescriptorSet and DecorationBinding. 14975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.opcode() == spv::OpDecorate) { 14985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.word(2) == spv::DecorationDescriptorSet) { 14995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis var_sets[insn.word(1)] = insn.word(3); 15005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 15015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 15025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.word(2) == spv::DecorationBinding) { 15035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis var_bindings[insn.word(1)] = insn.word(3); 15045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 15055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 15065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 15075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 15083a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes std::vector<std::pair<descriptor_slot_t, interface_var>> out; 15093a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes 15105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto id : accessible_ids) { 15115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto insn = src->get_def(id); 15125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(insn != src->end()); 15135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 15145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.opcode() == spv::OpVariable && 15155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (insn.word(3) == spv::StorageClassUniform || insn.word(3) == spv::StorageClassUniformConstant)) { 15165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned set = value_or_default(var_sets, insn.word(2), 0); 15175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned binding = value_or_default(var_bindings, insn.word(2), 0); 15185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1519b0436668e6594b8528e96de7bed208399fb2431dChris Forbes interface_var v = {}; 15205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis v.id = insn.word(2); 15215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis v.type_id = insn.word(1); 1522cefd4dd8e03c5dae11a05d04a03cb856190358e0Chris Forbes out.emplace_back(std::make_pair(set, binding), v); 15235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 15245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 15253a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes 15263a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes return out; 15275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 15285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1529edef66e03ed509994449d598f4fadea1a487d41bChris Forbesstatic bool validate_interface_between_stages(debug_report_data *report_data, shader_module const *producer, 1530031261d21af8907953dd763398ce9a23e65b8749Chris Forbes spirv_inst_iter producer_entrypoint, shader_stage_attributes const *producer_stage, 15315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis shader_module const *consumer, spirv_inst_iter consumer_entrypoint, 1532031261d21af8907953dd763398ce9a23e65b8749Chris Forbes shader_stage_attributes const *consumer_stage) { 15335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool pass = true; 15345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1535bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto outputs = 1536bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski collect_interface_by_location(producer, producer_entrypoint, spv::StorageClassOutput, producer_stage->arrayed_output); 1537bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto inputs = 1538bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski collect_interface_by_location(consumer, consumer_entrypoint, spv::StorageClassInput, consumer_stage->arrayed_input); 15395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 15405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto a_it = outputs.begin(); 15415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto b_it = inputs.begin(); 15425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 154325002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Maps sorted by key (location); walk them together to find mismatches 15445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis while ((outputs.size() > 0 && a_it != outputs.end()) || (inputs.size() && b_it != inputs.end())) { 15455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool a_at_end = outputs.size() == 0 || a_it == outputs.end(); 15465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool b_at_end = inputs.size() == 0 || b_it == inputs.end(); 15475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto a_first = a_at_end ? std::make_pair(0u, 0u) : a_it->first; 15485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto b_first = b_at_end ? std::make_pair(0u, 0u) : b_it->first; 15495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 15505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (b_at_end || ((!a_at_end) && (a_first < b_first))) { 1551bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 1552bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SHADER_CHECKER_OUTPUT_NOT_CONSUMED, "SC", "%s writes to output location %u.%u which is not consumed by %s", 1553bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski producer_stage->name, a_first.first, a_first.second, consumer_stage->name)) { 15545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pass = false; 15555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 15565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis a_it++; 15575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (a_at_end || a_first > b_first) { 1558bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 1559bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SHADER_CHECKER_INPUT_NOT_PRODUCED, "SC", "%s consumes input location %u.%u which is not written by %s", 1560bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski consumer_stage->name, b_first.first, b_first.second, producer_stage->name)) { 15615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pass = false; 15625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 15635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis b_it++; 15645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 1565fff9393206f66a154438e16fa0562c989f425498Chris Forbes // subtleties of arrayed interfaces: 1566fff9393206f66a154438e16fa0562c989f425498Chris Forbes // - if is_patch, then the member is not arrayed, even though the interface may be. 1567fff9393206f66a154438e16fa0562c989f425498Chris Forbes // - if is_block_member, then the extra array level of an arrayed interface is not 1568fff9393206f66a154438e16fa0562c989f425498Chris Forbes // expressed in the member type -- it's expressed in the block type. 15690f44c68c2575ba2fc83d8c8f2f5ea09548f40686Chris Forbes if (!types_match(producer, consumer, a_it->second.type_id, b_it->second.type_id, 1570fff9393206f66a154438e16fa0562c989f425498Chris Forbes producer_stage->arrayed_output && !a_it->second.is_patch && !a_it->second.is_block_member, 1571bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski consumer_stage->arrayed_input && !b_it->second.is_patch && !b_it->second.is_block_member, true)) { 1572bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 1573bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SHADER_CHECKER_INTERFACE_TYPE_MISMATCH, "SC", "Type mismatch on location %u.%u: '%s' vs '%s'", 1574bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski a_first.first, a_first.second, describe_type(producer, a_it->second.type_id).c_str(), 15759ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes describe_type(consumer, b_it->second.type_id).c_str())) { 15765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pass = false; 15775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 15785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 15790f44c68c2575ba2fc83d8c8f2f5ea09548f40686Chris Forbes if (a_it->second.is_patch != b_it->second.is_patch) { 1580bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 0, __LINE__, 1581bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SHADER_CHECKER_INTERFACE_TYPE_MISMATCH, "SC", 1582f706c50be3a9d4d1e131c2f43ee2fb443f028d30Chris Forbes "Decoration mismatch on location %u.%u: is per-%s in %s stage but " 1583bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "per-%s in %s stage", 1584bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski a_first.first, a_first.second, a_it->second.is_patch ? "patch" : "vertex", producer_stage->name, 15850f44c68c2575ba2fc83d8c8f2f5ea09548f40686Chris Forbes b_it->second.is_patch ? "patch" : "vertex", consumer_stage->name)) { 15860f44c68c2575ba2fc83d8c8f2f5ea09548f40686Chris Forbes pass = false; 15870f44c68c2575ba2fc83d8c8f2f5ea09548f40686Chris Forbes } 15880f44c68c2575ba2fc83d8c8f2f5ea09548f40686Chris Forbes } 158917c6bacf91ac671cb33212071b87b8ea782812f5Chris Forbes if (a_it->second.is_relaxed_precision != b_it->second.is_relaxed_precision) { 1590bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 0, __LINE__, 1591bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SHADER_CHECKER_INTERFACE_TYPE_MISMATCH, "SC", 1592bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "Decoration mismatch on location %u.%u: %s and %s stages differ in precision", a_first.first, 1593bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski a_first.second, producer_stage->name, consumer_stage->name)) { 159417c6bacf91ac671cb33212071b87b8ea782812f5Chris Forbes pass = false; 159517c6bacf91ac671cb33212071b87b8ea782812f5Chris Forbes } 159617c6bacf91ac671cb33212071b87b8ea782812f5Chris Forbes } 15975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis a_it++; 15985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis b_it++; 15995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 16005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 16015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 16025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return pass; 16035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 16045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 16055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisenum FORMAT_TYPE { 1606f0fdde7692ffd5175435cc3bf3412b8468054f38Chris Forbes FORMAT_TYPE_FLOAT = 1, // UNORM, SNORM, FLOAT, USCALED, SSCALED, SRGB -- anything we consider float in the shader 1607f0fdde7692ffd5175435cc3bf3412b8468054f38Chris Forbes FORMAT_TYPE_SINT = 2, 1608f0fdde7692ffd5175435cc3bf3412b8468054f38Chris Forbes FORMAT_TYPE_UINT = 4, 16095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}; 16105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 16115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic unsigned get_format_type(VkFormat fmt) { 16125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis switch (fmt) { 1613cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_UNDEFINED: 1614f0fdde7692ffd5175435cc3bf3412b8468054f38Chris Forbes return 0; 1615cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R8_SINT: 1616cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R8G8_SINT: 1617cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R8G8B8_SINT: 1618cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R8G8B8A8_SINT: 1619cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R16_SINT: 1620cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R16G16_SINT: 1621cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R16G16B16_SINT: 1622cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R16G16B16A16_SINT: 1623cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R32_SINT: 1624cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R32G32_SINT: 1625cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R32G32B32_SINT: 1626cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R32G32B32A32_SINT: 1627cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64_SINT: 1628cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64G64_SINT: 1629cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64G64B64_SINT: 1630cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64G64B64A64_SINT: 1631cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_B8G8R8_SINT: 1632cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_B8G8R8A8_SINT: 1633cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_A8B8G8R8_SINT_PACK32: 1634cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_A2B10G10R10_SINT_PACK32: 1635cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_A2R10G10B10_SINT_PACK32: 1636cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return FORMAT_TYPE_SINT; 1637cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R8_UINT: 1638cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R8G8_UINT: 1639cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R8G8B8_UINT: 1640cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R8G8B8A8_UINT: 1641cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R16_UINT: 1642cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R16G16_UINT: 1643cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R16G16B16_UINT: 1644cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R16G16B16A16_UINT: 1645cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R32_UINT: 1646cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R32G32_UINT: 1647cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R32G32B32_UINT: 1648cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R32G32B32A32_UINT: 1649cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64_UINT: 1650cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64G64_UINT: 1651cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64G64B64_UINT: 1652cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64G64B64A64_UINT: 1653cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_B8G8R8_UINT: 1654cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_B8G8R8A8_UINT: 1655cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_A8B8G8R8_UINT_PACK32: 1656cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_A2B10G10R10_UINT_PACK32: 1657cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_A2R10G10B10_UINT_PACK32: 1658cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return FORMAT_TYPE_UINT; 1659c3e75516f42455703d7577ecf7fb5aceb876e1f7Chris Forbes case VK_FORMAT_D16_UNORM_S8_UINT: 1660c3e75516f42455703d7577ecf7fb5aceb876e1f7Chris Forbes case VK_FORMAT_D24_UNORM_S8_UINT: 1661c3e75516f42455703d7577ecf7fb5aceb876e1f7Chris Forbes case VK_FORMAT_D32_SFLOAT_S8_UINT: 1662c3e75516f42455703d7577ecf7fb5aceb876e1f7Chris Forbes return FORMAT_TYPE_FLOAT | FORMAT_TYPE_UINT; 1663cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 1664cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return FORMAT_TYPE_FLOAT; 16655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 16665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 16675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 166825002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// characterizes a SPIR-V type appearing in an interface to a FF stage, for comparison to a VkFormat's characterization above. 16695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic unsigned get_fundamental_type(shader_module const *src, unsigned type) { 16705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto insn = src->get_def(type); 16715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(insn != src->end()); 16725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 16735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis switch (insn.opcode()) { 1674cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeInt: 1675cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return insn.word(3) ? FORMAT_TYPE_SINT : FORMAT_TYPE_UINT; 1676cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeFloat: 1677cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return FORMAT_TYPE_FLOAT; 1678cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeVector: 1679cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return get_fundamental_type(src, insn.word(2)); 1680cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeMatrix: 1681cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return get_fundamental_type(src, insn.word(2)); 1682cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeArray: 1683cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return get_fundamental_type(src, insn.word(2)); 1684cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypePointer: 1685cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return get_fundamental_type(src, insn.word(3)); 1686cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeImage: 1687cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return get_fundamental_type(src, insn.word(2)); 1688cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski 1689cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 1690f0fdde7692ffd5175435cc3bf3412b8468054f38Chris Forbes return 0; 16915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 16925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 16935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 16945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic uint32_t get_shader_stage_id(VkShaderStageFlagBits stage) { 16955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t bit_pos = u_ffs(stage); 16965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return bit_pos - 1; 16975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 16985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1699edef66e03ed509994449d598f4fadea1a487d41bChris Forbesstatic bool validate_vi_consistency(debug_report_data *report_data, VkPipelineVertexInputStateCreateInfo const *vi) { 170025002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Walk the binding descriptions, which describe the step rate and stride of each vertex buffer. Each binding should 170125002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // be specified only once. 17025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_map<uint32_t, VkVertexInputBindingDescription const *> bindings; 17035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool pass = true; 17045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 17055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (unsigned i = 0; i < vi->vertexBindingDescriptionCount; i++) { 17065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto desc = &vi->pVertexBindingDescriptions[i]; 17075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto &binding = bindings[desc->binding]; 17085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (binding) { 17094f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes // TODO: VALIDATION_ERROR_02105 perhaps? 1710bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 1711bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SHADER_CHECKER_INCONSISTENT_VI, "SC", "Duplicate vertex input binding descriptions for binding %d", 1712bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski desc->binding)) { 17135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pass = false; 17145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 17165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis binding = desc; 17175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 17205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return pass; 17215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 17225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1723edef66e03ed509994449d598f4fadea1a487d41bChris Forbesstatic bool validate_vi_against_vs_inputs(debug_report_data *report_data, VkPipelineVertexInputStateCreateInfo const *vi, 17245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis shader_module const *vs, spirv_inst_iter entrypoint) { 17255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool pass = true; 17265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 17273a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes auto inputs = collect_interface_by_location(vs, entrypoint, spv::StorageClassInput, false); 17285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 172925002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Build index by location 17305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::map<uint32_t, VkVertexInputAttributeDescription const *> attribs; 17315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (vi) { 1732c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes for (unsigned i = 0; i < vi->vertexAttributeDescriptionCount; i++) { 1733c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes auto num_locations = get_locations_consumed_by_format(vi->pVertexAttributeDescriptions[i].format); 1734c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes for (auto j = 0u; j < num_locations; j++) { 1735c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes attribs[vi->pVertexAttributeDescriptions[i].location + j] = &vi->pVertexAttributeDescriptions[i]; 1736c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes } 1737c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes } 17385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 17405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto it_a = attribs.begin(); 17415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto it_b = inputs.begin(); 17421730e0dd28b3abc660b4e4704cf6d414f7fd4ad6Chris Forbes bool used = false; 17435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 17445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis while ((attribs.size() > 0 && it_a != attribs.end()) || (inputs.size() > 0 && it_b != inputs.end())) { 17455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool a_at_end = attribs.size() == 0 || it_a == attribs.end(); 17465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool b_at_end = inputs.size() == 0 || it_b == inputs.end(); 17475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto a_first = a_at_end ? 0 : it_a->first; 17485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto b_first = b_at_end ? 0 : it_b->first.first; 17495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!a_at_end && (b_at_end || a_first < b_first)) { 17501730e0dd28b3abc660b4e4704cf6d414f7fd4ad6Chris Forbes if (!used && log_msg(report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, 1751bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski __LINE__, SHADER_CHECKER_OUTPUT_NOT_CONSUMED, "SC", 1752bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "Vertex attribute at location %d not consumed by vertex shader", a_first)) { 17535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pass = false; 17545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17551730e0dd28b3abc660b4e4704cf6d414f7fd4ad6Chris Forbes used = false; 17565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis it_a++; 17575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (!b_at_end && (a_at_end || b_first < a_first)) { 1758bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 0, __LINE__, 1759bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SHADER_CHECKER_INPUT_NOT_PRODUCED, "SC", "Vertex shader consumes input at location %d but not provided", 17605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis b_first)) { 17615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pass = false; 17625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis it_b++; 17645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 17655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned attrib_type = get_format_type(it_a->second->format); 17665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned input_type = get_fundamental_type(vs, it_b->second.type_id); 17675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 176825002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Type checking 1769f0fdde7692ffd5175435cc3bf3412b8468054f38Chris Forbes if (!(attrib_type & input_type)) { 1770bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 1771bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SHADER_CHECKER_INTERFACE_TYPE_MISMATCH, "SC", 17724b5890faffa54a735782a6b0a628a991ddc86944Mike Weiblen "Attribute type of `%s` at location %d does not match vertex shader input type of `%s`", 1773bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski string_VkFormat(it_a->second->format), a_first, describe_type(vs, it_b->second.type_id).c_str())) { 17745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pass = false; 17755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 177825002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // OK! 17791730e0dd28b3abc660b4e4704cf6d414f7fd4ad6Chris Forbes used = true; 17805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis it_b++; 17815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 17845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return pass; 17855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 17865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1787edef66e03ed509994449d598f4fadea1a487d41bChris Forbesstatic bool validate_fs_outputs_against_render_pass(debug_report_data *report_data, shader_module const *fs, 17888da1edac0fbed13831b2f458f27c51e64d6210ffTobin Ehlis spirv_inst_iter entrypoint, VkRenderPassCreateInfo const *rpci, 17898da1edac0fbed13831b2f458f27c51e64d6210ffTobin Ehlis uint32_t subpass_index) { 1790025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes std::map<uint32_t, VkFormat> color_attachments; 17918da1edac0fbed13831b2f458f27c51e64d6210ffTobin Ehlis auto subpass = rpci->pSubpasses[subpass_index]; 17928da1edac0fbed13831b2f458f27c51e64d6210ffTobin Ehlis for (auto i = 0u; i < subpass.colorAttachmentCount; ++i) { 1793d9da90d92748c37962766868f8b0354637672c2aTobin Ehlis uint32_t attachment = subpass.pColorAttachments[i].attachment; 1794cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (attachment == VK_ATTACHMENT_UNUSED) continue; 1795d9da90d92748c37962766868f8b0354637672c2aTobin Ehlis if (rpci->pAttachments[attachment].format != VK_FORMAT_UNDEFINED) { 1796d9da90d92748c37962766868f8b0354637672c2aTobin Ehlis color_attachments[i] = rpci->pAttachments[attachment].format; 1797025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes } 1798025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes } 1799025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes 18005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool pass = true; 18015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 180225002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // TODO: dual source blend index (spv::DecIndex, zero if not provided) 18035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 18043a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes auto outputs = collect_interface_by_location(fs, entrypoint, spv::StorageClassOutput, false); 18055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1806025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes auto it_a = outputs.begin(); 1807025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes auto it_b = color_attachments.begin(); 18085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 180925002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Walk attachment list and outputs together 1810025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes 1811025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes while ((outputs.size() > 0 && it_a != outputs.end()) || (color_attachments.size() > 0 && it_b != color_attachments.end())) { 1812025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes bool a_at_end = outputs.size() == 0 || it_a == outputs.end(); 1813025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes bool b_at_end = color_attachments.size() == 0 || it_b == color_attachments.end(); 18145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1815025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes if (!a_at_end && (b_at_end || it_a->first.first < it_b->first)) { 1816bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 1817bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SHADER_CHECKER_OUTPUT_NOT_CONSUMED, "SC", 1818d79335137b414d5f89284a9ab3e014beb4ada3ebMike Weiblen "fragment shader writes to output location %d with no matching attachment", it_a->first.first)) { 18195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pass = false; 18205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 1821025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes it_a++; 1822025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes } else if (!b_at_end && (a_at_end || it_a->first.first > it_b->first)) { 1823bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 1824bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SHADER_CHECKER_INPUT_NOT_PRODUCED, "SC", "Attachment %d not written by fragment shader", it_b->first)) { 18255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pass = false; 18265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 1827025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes it_b++; 18285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 1829025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes unsigned output_type = get_fundamental_type(fs, it_a->second.type_id); 1830025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes unsigned att_type = get_format_type(it_b->second); 18315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 183225002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Type checking 1833f0fdde7692ffd5175435cc3bf3412b8468054f38Chris Forbes if (!(output_type & att_type)) { 1834bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 1835bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SHADER_CHECKER_INTERFACE_TYPE_MISMATCH, "SC", 1836d79335137b414d5f89284a9ab3e014beb4ada3ebMike Weiblen "Attachment %d of type `%s` does not match fragment shader output type of `%s`", it_b->first, 1837bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski string_VkFormat(it_b->second), describe_type(fs, it_a->second.type_id).c_str())) { 18385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pass = false; 18395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 18405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 18415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 184225002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // OK! 1843025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes it_a++; 1844025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes it_b++; 18455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 18465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 18475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 18485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return pass; 18495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 18505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 185125002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// For some analyses, we need to know about all ids referenced by the static call tree of a particular entrypoint. This is 185225002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// important for identifying the set of shader resources actually used by an entrypoint, for example. 185325002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// Note: we only explore parts of the image which might actually contain ids we care about for the above analyses. 185425002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// - NOT the shader input/output interfaces. 185525002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// 185625002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// TODO: The set of interesting opcodes here was determined by eyeballing the SPIRV spec. It might be worth 185725002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// converting parts of this to be generated from the machine-readable spec instead. 18583a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbesstatic std::unordered_set<uint32_t> mark_accessible_ids(shader_module const *src, spirv_inst_iter entrypoint) { 18593a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes std::unordered_set<uint32_t> ids; 18605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_set<uint32_t> worklist; 18615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis worklist.insert(entrypoint.word(2)); 18625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 18635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis while (!worklist.empty()) { 18645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto id_iter = worklist.begin(); 18655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto id = *id_iter; 18665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis worklist.erase(id_iter); 18675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 18685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto insn = src->get_def(id); 18695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn == src->end()) { 187025002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // ID is something we didn't collect in build_def_index. that's OK -- we'll stumble across all kinds of things here 187125002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // that we may not care about. 18725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis continue; 18735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 18745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 187525002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Try to add to the output set 18765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!ids.insert(id).second) { 1877cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski continue; // If we already saw this id, we don't want to walk it again. 18785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 18795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 18805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis switch (insn.opcode()) { 1881cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpFunction: 1882cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Scan whole body of the function, enlisting anything interesting 1883cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski while (++insn, insn.opcode() != spv::OpFunctionEnd) { 1884cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski switch (insn.opcode()) { 1885cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpLoad: 1886cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicLoad: 1887cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicExchange: 1888cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicCompareExchange: 1889cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicCompareExchangeWeak: 1890cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicIIncrement: 1891cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicIDecrement: 1892cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicIAdd: 1893cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicISub: 1894cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicSMin: 1895cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicUMin: 1896cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicSMax: 1897cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicUMax: 1898cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicAnd: 1899cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicOr: 1900cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicXor: 1901cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski worklist.insert(insn.word(3)); // ptr 1902cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1903cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpStore: 1904cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicStore: 1905cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski worklist.insert(insn.word(1)); // ptr 1906cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1907cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAccessChain: 1908cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpInBoundsAccessChain: 1909cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski worklist.insert(insn.word(3)); // base ptr 1910cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1911cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpSampledImage: 1912cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSampleImplicitLod: 1913cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSampleExplicitLod: 1914cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSampleDrefImplicitLod: 1915cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSampleDrefExplicitLod: 1916cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSampleProjImplicitLod: 1917cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSampleProjExplicitLod: 1918cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSampleProjDrefImplicitLod: 1919cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSampleProjDrefExplicitLod: 1920cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageFetch: 1921cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageGather: 1922cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageDrefGather: 1923cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageRead: 1924cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImage: 1925cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageQueryFormat: 1926cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageQueryOrder: 1927cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageQuerySizeLod: 1928cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageQuerySize: 1929cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageQueryLod: 1930cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageQueryLevels: 1931cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageQuerySamples: 1932cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSparseSampleImplicitLod: 1933cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSparseSampleExplicitLod: 1934cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSparseSampleDrefImplicitLod: 1935cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSparseSampleDrefExplicitLod: 1936cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSparseSampleProjImplicitLod: 1937cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSparseSampleProjExplicitLod: 1938cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSparseSampleProjDrefImplicitLod: 1939cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSparseSampleProjDrefExplicitLod: 1940cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSparseFetch: 1941cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSparseGather: 1942cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSparseDrefGather: 1943cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageTexelPointer: 1944cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski worklist.insert(insn.word(3)); // Image or sampled image 1945cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1946cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageWrite: 1947cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski worklist.insert(insn.word(1)); // Image -- different operand order to above 1948cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1949cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpFunctionCall: 1950cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski for (uint32_t i = 3; i < insn.len(); i++) { 1951cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski worklist.insert(insn.word(i)); // fn itself, and all args 1952cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 1953cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 19545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1955cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpExtInst: 1956cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski for (uint32_t i = 5; i < insn.len(); i++) { 1957cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski worklist.insert(insn.word(i)); // Operands to ext inst 1958cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 1959cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 19605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 19615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 1962cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 19635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 19645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 19653a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes 19663a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes return ids; 19675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 19685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1969edef66e03ed509994449d598f4fadea1a487d41bChris Forbesstatic bool validate_push_constant_block_against_pipeline(debug_report_data *report_data, 1970416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis std::vector<VkPushConstantRange> const *push_constant_ranges, 19715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis shader_module const *src, spirv_inst_iter type, 19725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkShaderStageFlagBits stage) { 19735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool pass = true; 19745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 197525002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Strip off ptrs etc 19765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis type = get_struct_type(src, type, false); 19775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(type != src->end()); 19785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 197925002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Validate directly off the offsets. this isn't quite correct for arrays and matrices, but is a good first step. 198025002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // TODO: arrays, matrices, weird sizes 19815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto insn : *src) { 19825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.opcode() == spv::OpMemberDecorate && insn.word(1) == type.word(1)) { 19835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.word(3) == spv::DecorationOffset) { 19845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned offset = insn.word(4); 1985cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski auto size = 4; // Bytes; TODO: calculate this based on the type 19865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 19875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool found_range = false; 1988416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis for (auto const &range : *push_constant_ranges) { 19895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (range.offset <= offset && range.offset + range.size >= offset + size) { 19905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis found_range = true; 19915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 19925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if ((range.stageFlags & stage) == 0) { 1993bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 1994bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SHADER_CHECKER_PUSH_CONSTANT_NOT_ACCESSIBLE_FROM_STAGE, "SC", 19955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis "Push constant range covering variable starting at " 19965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis "offset %u not accessible from stage %s", 19975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis offset, string_VkShaderStageFlagBits(stage))) { 19985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pass = false; 19995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 20005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 20015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 20025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis break; 20035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 20045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 20055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 20065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!found_range) { 2007bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 2008bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SHADER_CHECKER_PUSH_CONSTANT_OUT_OF_RANGE, "SC", 20095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis "Push constant range covering variable starting at " 20105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis "offset %u not declared in layout", 20115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis offset)) { 20125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pass = false; 20135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 20145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 20155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 20165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 20175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 20185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 20195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return pass; 20205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 20215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2022edef66e03ed509994449d598f4fadea1a487d41bChris Forbesstatic bool validate_push_constant_usage(debug_report_data *report_data, 2023416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis std::vector<VkPushConstantRange> const *push_constant_ranges, shader_module const *src, 20245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_set<uint32_t> accessible_ids, VkShaderStageFlagBits stage) { 20255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool pass = true; 20265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 20275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto id : accessible_ids) { 20285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto def_insn = src->get_def(id); 20295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (def_insn.opcode() == spv::OpVariable && def_insn.word(3) == spv::StorageClassPushConstant) { 2030416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis pass &= validate_push_constant_block_against_pipeline(report_data, push_constant_ranges, src, 2031416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis src->get_def(def_insn.word(1)), stage); 20325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 20335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 20345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 20355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return pass; 20365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 20375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2038fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis// For given pipelineLayout verify that the set_layout_node at slot.first 2039fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis// has the requested binding at slot.second and return ptr to that binding 2040bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic VkDescriptorSetLayoutBinding const *get_descriptor_binding(PIPELINE_LAYOUT_NODE const *pipelineLayout, 2041bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski descriptor_slot_t slot) { 2042cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!pipelineLayout) return nullptr; 20435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2044cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (slot.first >= pipelineLayout->set_layouts.size()) return nullptr; 20455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2046416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis return pipelineLayout->set_layouts[slot.first]->GetDescriptorSetLayoutBindingPtrFromBinding(slot.second); 20475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 20485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 20495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Check object status for selected flag state 205051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool validate_status(layer_data *dev_data, GLOBAL_CB_NODE *pNode, CBStatusFlags status_mask, VkFlags msg_flags, 20514f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes const char *fail_msg, UNIQUE_VALIDATION_ERROR_CODE const msg_code) { 20523d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis if (!(pNode->status & status_mask)) { 20534f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes char const *const message = validation_error_map[msg_code]; 205451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis return log_msg(dev_data->report_data, msg_flags, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 20554f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes reinterpret_cast<const uint64_t &>(pNode->commandBuffer), __LINE__, msg_code, "DS", 20564f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "command buffer object 0x%p: %s. %s.", pNode->commandBuffer, fail_msg, message); 20575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 2058e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves return false; 20595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 20605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 20615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Retrieve pipeline node ptr for given pipeline object 206251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic PIPELINE_STATE *getPipelineState(layer_data const *dev_data, VkPipeline pipeline) { 206351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis auto it = dev_data->pipelineMap.find(pipeline); 206451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (it == dev_data->pipelineMap.end()) { 2065ea8349eeee76ae2859c10870fd8bd9e60309eb28Chris Forbes return nullptr; 20665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 2067ea8349eeee76ae2859c10870fd8bd9e60309eb28Chris Forbes return it->second; 20685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 20695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 20709a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisRENDER_PASS_STATE *GetRenderPassState(layer_data const *dev_data, VkRenderPass renderpass) { 207151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis auto it = dev_data->renderPassMap.find(renderpass); 207251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (it == dev_data->renderPassMap.end()) { 207316387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes return nullptr; 207416387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes } 2075fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes return it->second.get(); 207616387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes} 207716387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes 20789a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisFRAMEBUFFER_STATE *GetFramebufferState(const layer_data *dev_data, VkFramebuffer framebuffer) { 207951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis auto it = dev_data->frameBufferMap.find(framebuffer); 208051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (it == dev_data->frameBufferMap.end()) { 2081f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes return nullptr; 2082f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes } 208304861caca7eb93a5241b164e8480bb93c826902cTobin Ehlis return it->second.get(); 2084f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes} 2085f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes 20869a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehliscvdescriptorset::DescriptorSetLayout const *GetDescriptorSetLayout(layer_data const *dev_data, VkDescriptorSetLayout dsLayout) { 208751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis auto it = dev_data->descriptorSetLayoutMap.find(dsLayout); 208851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (it == dev_data->descriptorSetLayoutMap.end()) { 208911f1fde2721c198a619e4a22fff60eef9a16fae8Chris Forbes return nullptr; 209011f1fde2721c198a619e4a22fff60eef9a16fae8Chris Forbes } 209111f1fde2721c198a619e4a22fff60eef9a16fae8Chris Forbes return it->second; 209211f1fde2721c198a619e4a22fff60eef9a16fae8Chris Forbes} 209311f1fde2721c198a619e4a22fff60eef9a16fae8Chris Forbes 209451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic PIPELINE_LAYOUT_NODE const *getPipelineLayout(layer_data const *dev_data, VkPipelineLayout pipeLayout) { 209551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis auto it = dev_data->pipelineLayoutMap.find(pipeLayout); 209651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (it == dev_data->pipelineLayoutMap.end()) { 20974a45a42023b281f55953222c1a6c3e80f50e5f2aChris Forbes return nullptr; 20984a45a42023b281f55953222c1a6c3e80f50e5f2aChris Forbes } 20994a45a42023b281f55953222c1a6c3e80f50e5f2aChris Forbes return &it->second; 21004a45a42023b281f55953222c1a6c3e80f50e5f2aChris Forbes} 21014a45a42023b281f55953222c1a6c3e80f50e5f2aChris Forbes 2102e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves// Return true if for a given PSO, the given state enum is dynamic, else return false 21034c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlisstatic bool isDynamic(const PIPELINE_STATE *pPipeline, const VkDynamicState state) { 21045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pPipeline && pPipeline->graphicsPipelineCI.pDynamicState) { 21055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < pPipeline->graphicsPipelineCI.pDynamicState->dynamicStateCount; i++) { 2106cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (state == pPipeline->graphicsPipelineCI.pDynamicState->pDynamicStates[i]) return true; 21075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 21085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 2109e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves return false; 21105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 21115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 21125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Validate state stored as flags at time of draw call 21134f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayesstatic bool validate_draw_state_flags(layer_data *dev_data, GLOBAL_CB_NODE *pCB, const PIPELINE_STATE *pPipe, bool indexed, 21144f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes UNIQUE_VALIDATION_ERROR_CODE const msg_code) { 21159c4006684a13db43f0dbc8d0015a9ef34872ca09Chris Forbes bool result = false; 2116ca546210846c65808717f8875deae39bd227c240Tobin Ehlis if (pPipe->graphicsPipelineCI.pInputAssemblyState && 2117ca546210846c65808717f8875deae39bd227c240Tobin Ehlis ((pPipe->graphicsPipelineCI.pInputAssemblyState->topology == VK_PRIMITIVE_TOPOLOGY_LINE_LIST) || 2118ca546210846c65808717f8875deae39bd227c240Tobin Ehlis (pPipe->graphicsPipelineCI.pInputAssemblyState->topology == VK_PRIMITIVE_TOPOLOGY_LINE_STRIP))) { 21193d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis result |= validate_status(dev_data, pCB, CBSTATUS_LINE_WIDTH_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, 21204f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "Dynamic line width state not set for this command buffer", msg_code); 21213d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 212245824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves if (pPipe->graphicsPipelineCI.pRasterizationState && 212345824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves (pPipe->graphicsPipelineCI.pRasterizationState->depthBiasEnable == VK_TRUE)) { 21243d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis result |= validate_status(dev_data, pCB, CBSTATUS_DEPTH_BIAS_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, 21254f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "Dynamic depth bias state not set for this command buffer", msg_code); 21263d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 21273d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis if (pPipe->blendConstantsEnabled) { 21283d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis result |= validate_status(dev_data, pCB, CBSTATUS_BLEND_CONSTANTS_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, 21294f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "Dynamic blend constants state not set for this command buffer", msg_code); 21303d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 213145824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves if (pPipe->graphicsPipelineCI.pDepthStencilState && 213245824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves (pPipe->graphicsPipelineCI.pDepthStencilState->depthBoundsTestEnable == VK_TRUE)) { 21333d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis result |= validate_status(dev_data, pCB, CBSTATUS_DEPTH_BOUNDS_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, 21344f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "Dynamic depth bounds state not set for this command buffer", msg_code); 21353d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 213645824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves if (pPipe->graphicsPipelineCI.pDepthStencilState && 213745824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves (pPipe->graphicsPipelineCI.pDepthStencilState->stencilTestEnable == VK_TRUE)) { 21383d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis result |= validate_status(dev_data, pCB, CBSTATUS_STENCIL_READ_MASK_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, 21394f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "Dynamic stencil read mask state not set for this command buffer", msg_code); 21403d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis result |= validate_status(dev_data, pCB, CBSTATUS_STENCIL_WRITE_MASK_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, 21414f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "Dynamic stencil write mask state not set for this command buffer", msg_code); 21423d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis result |= validate_status(dev_data, pCB, CBSTATUS_STENCIL_REFERENCE_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, 21434f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "Dynamic stencil reference state not set for this command buffer", msg_code); 21443d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 21451c130ea631a82716dc7334de17767536525f2292Tobin Ehlis if (indexed) { 21463d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis result |= validate_status(dev_data, pCB, CBSTATUS_INDEX_BUFFER_BOUND, VK_DEBUG_REPORT_ERROR_BIT_EXT, 21474f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "Index buffer object not bound to this command buffer when Indexed Draw attempted", msg_code); 21483d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 21494f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes 21505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 21515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 21525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 21535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Verify attachment reference compatibility according to spec 21545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// If one array is larger, treat missing elements of shorter array as VK_ATTACHMENT_UNUSED & other array much match this 21555ca3c071afc98f9144f489b74aa3affaa93633b0Mark Lobodzinski// If both AttachmentReference arrays have requested index, check their corresponding AttachmentDescriptions 21565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// to make sure that format and samples counts match. 21575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// If not, they are not compatible. 21585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic bool attachment_references_compatible(const uint32_t index, const VkAttachmentReference *pPrimary, 21595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const uint32_t primaryCount, const VkAttachmentDescription *pPrimaryAttachments, 21605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkAttachmentReference *pSecondary, const uint32_t secondaryCount, 21615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkAttachmentDescription *pSecondaryAttachments) { 2162e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis // Check potential NULL cases first to avoid nullptr issues later 2163e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis if (pPrimary == nullptr) { 2164e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis if (pSecondary == nullptr) { 2165e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis return true; 2166e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis } 2167e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis return false; 2168e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis } else if (pSecondary == nullptr) { 2169e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis return false; 2170e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis } 2171cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (index >= primaryCount) { // Check secondary as if primary is VK_ATTACHMENT_UNUSED 2172cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (VK_ATTACHMENT_UNUSED == pSecondary[index].attachment) return true; 2173cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else if (index >= secondaryCount) { // Check primary as if secondary is VK_ATTACHMENT_UNUSED 2174cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (VK_ATTACHMENT_UNUSED == pPrimary[index].attachment) return true; 2175cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else { // Format and sample count must match 21765ca3c071afc98f9144f489b74aa3affaa93633b0Mark Lobodzinski if ((pPrimary[index].attachment == VK_ATTACHMENT_UNUSED) && (pSecondary[index].attachment == VK_ATTACHMENT_UNUSED)) { 21775ca3c071afc98f9144f489b74aa3affaa93633b0Mark Lobodzinski return true; 21785ca3c071afc98f9144f489b74aa3affaa93633b0Mark Lobodzinski } else if ((pPrimary[index].attachment == VK_ATTACHMENT_UNUSED) || (pSecondary[index].attachment == VK_ATTACHMENT_UNUSED)) { 21795ca3c071afc98f9144f489b74aa3affaa93633b0Mark Lobodzinski return false; 21805ca3c071afc98f9144f489b74aa3affaa93633b0Mark Lobodzinski } 21815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if ((pPrimaryAttachments[pPrimary[index].attachment].format == 21825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pSecondaryAttachments[pSecondary[index].attachment].format) && 21835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (pPrimaryAttachments[pPrimary[index].attachment].samples == 21845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pSecondaryAttachments[pSecondary[index].attachment].samples)) 21855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return true; 21865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 21875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Format and sample counts didn't match 21885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 21895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 2190a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis// TODO : Scrub verify_renderpass_compatibility() and validateRenderPassCompatibility() and unify them and/or share code 21918da1edac0fbed13831b2f458f27c51e64d6210ffTobin Ehlis// For given primary RenderPass object and secondry RenderPassCreateInfo, verify that they're compatible 219251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool verify_renderpass_compatibility(const layer_data *dev_data, const VkRenderPassCreateInfo *primaryRPCI, 21938da1edac0fbed13831b2f458f27c51e64d6210ffTobin Ehlis const VkRenderPassCreateInfo *secondaryRPCI, string &errorMsg) { 21945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (primaryRPCI->subpassCount != secondaryRPCI->subpassCount) { 2195c07fa78efa7d4edfaa4ffbb0c2046ee8154b27beChris Forbes stringstream errorStr; 21965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis errorStr << "RenderPass for primary cmdBuffer has " << primaryRPCI->subpassCount 21975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis << " subpasses but renderPass for secondary cmdBuffer has " << secondaryRPCI->subpassCount << " subpasses."; 21985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis errorMsg = errorStr.str(); 21995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 22005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 22015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t spIndex = 0; 22025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (spIndex = 0; spIndex < primaryRPCI->subpassCount; ++spIndex) { 22035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // For each subpass, verify that corresponding color, input, resolve & depth/stencil attachment references are compatible 22045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t primaryColorCount = primaryRPCI->pSubpasses[spIndex].colorAttachmentCount; 22055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t secondaryColorCount = secondaryRPCI->pSubpasses[spIndex].colorAttachmentCount; 22065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t colorMax = std::max(primaryColorCount, secondaryColorCount); 22075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t cIdx = 0; cIdx < colorMax; ++cIdx) { 22085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!attachment_references_compatible(cIdx, primaryRPCI->pSubpasses[spIndex].pColorAttachments, primaryColorCount, 22095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis primaryRPCI->pAttachments, secondaryRPCI->pSubpasses[spIndex].pColorAttachments, 22105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis secondaryColorCount, secondaryRPCI->pAttachments)) { 2211c07fa78efa7d4edfaa4ffbb0c2046ee8154b27beChris Forbes stringstream errorStr; 22125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis errorStr << "color attachments at index " << cIdx << " of subpass index " << spIndex << " are not compatible."; 22135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis errorMsg = errorStr.str(); 22145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 22155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (!attachment_references_compatible(cIdx, primaryRPCI->pSubpasses[spIndex].pResolveAttachments, 22165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis primaryColorCount, primaryRPCI->pAttachments, 22175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis secondaryRPCI->pSubpasses[spIndex].pResolveAttachments, 22185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis secondaryColorCount, secondaryRPCI->pAttachments)) { 2219c07fa78efa7d4edfaa4ffbb0c2046ee8154b27beChris Forbes stringstream errorStr; 22205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis errorStr << "resolve attachments at index " << cIdx << " of subpass index " << spIndex << " are not compatible."; 22215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis errorMsg = errorStr.str(); 22225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 22235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 22245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 2225fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes 2226bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (!attachment_references_compatible(0, primaryRPCI->pSubpasses[spIndex].pDepthStencilAttachment, 1, 2227bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski primaryRPCI->pAttachments, secondaryRPCI->pSubpasses[spIndex].pDepthStencilAttachment, 2228fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes 1, secondaryRPCI->pAttachments)) { 2229c07fa78efa7d4edfaa4ffbb0c2046ee8154b27beChris Forbes stringstream errorStr; 2230fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes errorStr << "depth/stencil attachments of subpass index " << spIndex << " are not compatible."; 2231fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes errorMsg = errorStr.str(); 2232fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes return false; 2233fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes } 2234fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes 22355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t primaryInputCount = primaryRPCI->pSubpasses[spIndex].inputAttachmentCount; 22365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t secondaryInputCount = secondaryRPCI->pSubpasses[spIndex].inputAttachmentCount; 22375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t inputMax = std::max(primaryInputCount, secondaryInputCount); 22385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < inputMax; ++i) { 22395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!attachment_references_compatible(i, primaryRPCI->pSubpasses[spIndex].pInputAttachments, primaryColorCount, 22405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis primaryRPCI->pAttachments, secondaryRPCI->pSubpasses[spIndex].pInputAttachments, 22415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis secondaryColorCount, secondaryRPCI->pAttachments)) { 2242c07fa78efa7d4edfaa4ffbb0c2046ee8154b27beChris Forbes stringstream errorStr; 22435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis errorStr << "input attachments at index " << i << " of subpass index " << spIndex << " are not compatible."; 22445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis errorMsg = errorStr.str(); 22455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 22465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 22475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 22485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 22495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return true; 22505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 22515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2252397d27da37095073c8b86f9ff5289d0a39ce486eTobin Ehlis// For given cvdescriptorset::DescriptorSet, verify that its Set is compatible w/ the setLayout corresponding to 2253397d27da37095073c8b86f9ff5289d0a39ce486eTobin Ehlis// pipelineLayout[layoutIndex] 225451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool verify_set_layout_compatibility(layer_data *dev_data, const cvdescriptorset::DescriptorSet *descriptor_set, 225569b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis PIPELINE_LAYOUT_NODE const *pipeline_layout, const uint32_t layoutIndex, 225669b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis string &errorMsg) { 2257416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis auto num_sets = pipeline_layout->set_layouts.size(); 22589b5d124aff50234cb0450e1b805baef577c90d83Tobin Ehlis if (layoutIndex >= num_sets) { 2259c07fa78efa7d4edfaa4ffbb0c2046ee8154b27beChris Forbes stringstream errorStr; 226069b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis errorStr << "VkPipelineLayout (" << pipeline_layout->layout << ") only contains " << num_sets 226169b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis << " setLayouts corresponding to sets 0-" << num_sets - 1 << ", but you're attempting to bind set to index " 226269b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis << layoutIndex; 22635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis errorMsg = errorStr.str(); 22645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 22655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 2266416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis auto layout_node = pipeline_layout->set_layouts[layoutIndex]; 22671c130ea631a82716dc7334de17767536525f2292Tobin Ehlis return descriptor_set->IsCompatible(layout_node, &errorMsg); 22685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 22695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 22705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Validate that data for each specialization entry is fully contained within the buffer. 2271edef66e03ed509994449d598f4fadea1a487d41bChris Forbesstatic bool validate_specialization_offsets(debug_report_data *report_data, VkPipelineShaderStageCreateInfo const *info) { 2272e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool pass = true; 22735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 22745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkSpecializationInfo const *spec = info->pSpecializationInfo; 22755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 22765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (spec) { 22775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto i = 0u; i < spec->mapEntryCount; i++) { 22784f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes // TODO: This is a good place for VALIDATION_ERROR_00589. 22795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (spec->pMapEntries[i].offset + spec->pMapEntries[i].size > spec->dataSize) { 22804f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 0, __LINE__, 22814f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes VALIDATION_ERROR_00590, "SC", 22825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis "Specialization entry %u (for constant id %u) references memory outside provided " 22835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis "specialization data (bytes %u.." PRINTF_SIZE_T_SPECIFIER "; " PRINTF_SIZE_T_SPECIFIER 22844f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes " bytes provided). %s.", 22855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis i, spec->pMapEntries[i].constantID, spec->pMapEntries[i].offset, 22864f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes spec->pMapEntries[i].offset + spec->pMapEntries[i].size - 1, spec->dataSize, 22874f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes validation_error_map[VALIDATION_ERROR_00590])) { 2288e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves pass = false; 22895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 22905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 22915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 22925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 22935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 22945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return pass; 22955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 22965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2297bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic bool descriptor_type_match(shader_module const *module, uint32_t type_id, VkDescriptorType descriptor_type, 2298bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski unsigned &descriptor_count) { 22995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto type = module->get_def(type_id); 23005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 23011b8c581791ac3c05d7829e04a2d8ecb964b8f2a6Chris Forbes descriptor_count = 1; 23021b8c581791ac3c05d7829e04a2d8ecb964b8f2a6Chris Forbes 230325002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Strip off any array or ptrs. Where we remove array levels, adjust the descriptor count for each dimension. 23045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis while (type.opcode() == spv::OpTypeArray || type.opcode() == spv::OpTypePointer) { 23057b892d2fc502b57d26dc9bff61b0f23cccc595fdChris Forbes if (type.opcode() == spv::OpTypeArray) { 23067b892d2fc502b57d26dc9bff61b0f23cccc595fdChris Forbes descriptor_count *= get_constant_value(module, type.word(3)); 23077b892d2fc502b57d26dc9bff61b0f23cccc595fdChris Forbes type = module->get_def(type.word(2)); 2308bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski } else { 23097b892d2fc502b57d26dc9bff61b0f23cccc595fdChris Forbes type = module->get_def(type.word(3)); 23107b892d2fc502b57d26dc9bff61b0f23cccc595fdChris Forbes } 23115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 23125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 23135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis switch (type.opcode()) { 2314cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeStruct: { 2315cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski for (auto insn : *module) { 2316cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (insn.opcode() == spv::OpDecorate && insn.word(1) == type.word(1)) { 2317cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (insn.word(2) == spv::DecorationBlock) { 2318cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER || 2319cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; 2320cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else if (insn.word(2) == spv::DecorationBufferBlock) { 2321cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER || 2322cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC; 2323cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 23245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 23255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 23265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2327cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Invalid 2328cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return false; 2329cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 23305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2331cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeSampler: 2332cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return descriptor_type == VK_DESCRIPTOR_TYPE_SAMPLER || descriptor_type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 23335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2334cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeSampledImage: 2335cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER) { 2336cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Slight relaxation for some GLSL historical madness: samplerBuffer doesn't really have a sampler, and a texel 2337cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // buffer descriptor doesn't really provide one. Allow this slight mismatch. 2338cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski auto image_type = module->get_def(type.word(2)); 2339cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski auto dim = image_type.word(3); 2340cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski auto sampled = image_type.word(7); 2341cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return dim == spv::DimBuffer && sampled == 1; 2342cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 2343cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return descriptor_type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 23445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2345cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeImage: { 2346cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Many descriptor types backing image types-- depends on dimension and whether the image will be used with a sampler. 2347cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // SPIRV for Vulkan requires that sampled be 1 or 2 -- leaving the decision to runtime is unacceptable. 2348cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski auto dim = type.word(3); 2349cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski auto sampled = type.word(7); 23505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2351cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dim == spv::DimSubpassData) { 2352cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return descriptor_type == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; 2353cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else if (dim == spv::DimBuffer) { 2354cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (sampled == 1) { 2355cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; 2356cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else { 2357cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; 2358cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 2359cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else if (sampled == 1) { 2360cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return descriptor_type == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE || 2361cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski descriptor_type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 23625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 2363cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; 23645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 23655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 23665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2367cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // We shouldn't really see any other junk types -- but if we do, they're a mismatch. 2368cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 2369cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return false; // Mismatch 23705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 23715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 23725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 23734110a6be7a8a287d459475926985f71c27d01298Chris Forbesstatic bool require_feature(debug_report_data *report_data, VkBool32 feature, char const *feature_name) { 2374a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes if (!feature) { 2375bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 2376cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski SHADER_CHECKER_FEATURE_NOT_ENABLED, "SC", 2377cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Shader requires VkPhysicalDeviceFeatures::%s but is not " 2378cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "enabled on the device", 2379a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes feature_name)) { 2380a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes return false; 2381a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes } 2382a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes } 2383a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2384a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes return true; 2385a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes} 2386a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 23877b6006f355aaacf7fc7f0d575b40285b89ecd279Chris Forbesstatic bool require_extension(debug_report_data *report_data, VkBool32 extension, char const *extension_name) { 23887b6006f355aaacf7fc7f0d575b40285b89ecd279Chris Forbes if (!extension) { 23897b6006f355aaacf7fc7f0d575b40285b89ecd279Chris Forbes if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 23907b6006f355aaacf7fc7f0d575b40285b89ecd279Chris Forbes SHADER_CHECKER_FEATURE_NOT_ENABLED, "SC", 23917b6006f355aaacf7fc7f0d575b40285b89ecd279Chris Forbes "Shader requires extension %s but is not " 23927b6006f355aaacf7fc7f0d575b40285b89ecd279Chris Forbes "enabled on the device", 23937b6006f355aaacf7fc7f0d575b40285b89ecd279Chris Forbes extension_name)) { 23947b6006f355aaacf7fc7f0d575b40285b89ecd279Chris Forbes return false; 23957b6006f355aaacf7fc7f0d575b40285b89ecd279Chris Forbes } 23967b6006f355aaacf7fc7f0d575b40285b89ecd279Chris Forbes } 23977b6006f355aaacf7fc7f0d575b40285b89ecd279Chris Forbes 23987b6006f355aaacf7fc7f0d575b40285b89ecd279Chris Forbes return true; 23997b6006f355aaacf7fc7f0d575b40285b89ecd279Chris Forbes} 24007b6006f355aaacf7fc7f0d575b40285b89ecd279Chris Forbes 2401ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbesstatic bool validate_shader_capabilities(layer_data *dev_data, shader_module const *src) { 2402e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool pass = true; 2403a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2404ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes auto report_data = dev_data->report_data; 2405ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes auto const & enabledFeatures = dev_data->enabled_features; 2406ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes 2407a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes for (auto insn : *src) { 2408a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes if (insn.opcode() == spv::OpCapability) { 2409a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes switch (insn.word(1)) { 2410cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityMatrix: 2411cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityShader: 2412cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityInputAttachment: 2413cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilitySampled1D: 2414cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityImage1D: 2415cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilitySampledBuffer: 2416cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityImageBuffer: 2417cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityImageQuery: 2418cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityDerivativeControl: 2419cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Always supported by a Vulkan 1.0 implementation -- no feature bits. 2420cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2421a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2422cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityGeometry: 2423ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes pass &= require_feature(report_data, enabledFeatures.geometryShader, "geometryShader"); 2424cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2425a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2426cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityTessellation: 2427ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes pass &= require_feature(report_data, enabledFeatures.tessellationShader, "tessellationShader"); 2428cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2429a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2430cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityFloat64: 2431ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes pass &= require_feature(report_data, enabledFeatures.shaderFloat64, "shaderFloat64"); 2432cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2433a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2434cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityInt64: 2435ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes pass &= require_feature(report_data, enabledFeatures.shaderInt64, "shaderInt64"); 2436cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2437a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2438cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityTessellationPointSize: 2439cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityGeometryPointSize: 2440ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes pass &= require_feature(report_data, enabledFeatures.shaderTessellationAndGeometryPointSize, 2441cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "shaderTessellationAndGeometryPointSize"); 2442cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2443a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2444cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityImageGatherExtended: 2445ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes pass &= require_feature(report_data, enabledFeatures.shaderImageGatherExtended, "shaderImageGatherExtended"); 2446cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2447a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2448cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityStorageImageMultisample: 2449ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes pass &= require_feature(report_data, enabledFeatures.shaderStorageImageMultisample, 2450cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "shaderStorageImageMultisample"); 2451cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2452a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2453cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityUniformBufferArrayDynamicIndexing: 2454ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes pass &= require_feature(report_data, enabledFeatures.shaderUniformBufferArrayDynamicIndexing, 2455cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "shaderUniformBufferArrayDynamicIndexing"); 2456cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2457a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2458cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilitySampledImageArrayDynamicIndexing: 2459ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes pass &= require_feature(report_data, enabledFeatures.shaderSampledImageArrayDynamicIndexing, 2460cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "shaderSampledImageArrayDynamicIndexing"); 2461cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2462a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2463cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityStorageBufferArrayDynamicIndexing: 2464ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes pass &= require_feature(report_data, enabledFeatures.shaderStorageBufferArrayDynamicIndexing, 2465cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "shaderStorageBufferArrayDynamicIndexing"); 2466cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2467a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2468cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityStorageImageArrayDynamicIndexing: 2469ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes pass &= require_feature(report_data, enabledFeatures.shaderStorageImageArrayDynamicIndexing, 2470cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "shaderStorageImageArrayDynamicIndexing"); 2471cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2472a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2473cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityClipDistance: 2474ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes pass &= require_feature(report_data, enabledFeatures.shaderClipDistance, "shaderClipDistance"); 2475cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2476a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2477cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityCullDistance: 2478ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes pass &= require_feature(report_data, enabledFeatures.shaderCullDistance, "shaderCullDistance"); 2479cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2480a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2481cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityImageCubeArray: 2482ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes pass &= require_feature(report_data, enabledFeatures.imageCubeArray, "imageCubeArray"); 2483cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2484a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2485cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilitySampleRateShading: 2486ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes pass &= require_feature(report_data, enabledFeatures.sampleRateShading, "sampleRateShading"); 2487cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2488a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2489cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilitySparseResidency: 2490ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes pass &= require_feature(report_data, enabledFeatures.shaderResourceResidency, "shaderResourceResidency"); 2491cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2492a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2493cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityMinLod: 2494ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes pass &= require_feature(report_data, enabledFeatures.shaderResourceMinLod, "shaderResourceMinLod"); 2495cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2496a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2497cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilitySampledCubeArray: 2498ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes pass &= require_feature(report_data, enabledFeatures.imageCubeArray, "imageCubeArray"); 2499cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2500a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2501cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityImageMSArray: 2502ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes pass &= require_feature(report_data, enabledFeatures.shaderStorageImageMultisample, 2503cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "shaderStorageImageMultisample"); 2504cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2505a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2506cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityStorageImageExtendedFormats: 2507ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes pass &= require_feature(report_data, enabledFeatures.shaderStorageImageExtendedFormats, 2508cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "shaderStorageImageExtendedFormats"); 2509cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2510a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2511cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityInterpolationFunction: 2512ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes pass &= require_feature(report_data, enabledFeatures.sampleRateShading, "sampleRateShading"); 2513cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2514a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2515cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityStorageImageReadWithoutFormat: 2516ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes pass &= require_feature(report_data, enabledFeatures.shaderStorageImageReadWithoutFormat, 2517cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "shaderStorageImageReadWithoutFormat"); 2518cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2519a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2520cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityStorageImageWriteWithoutFormat: 2521ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes pass &= require_feature(report_data, enabledFeatures.shaderStorageImageWriteWithoutFormat, 2522cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "shaderStorageImageWriteWithoutFormat"); 2523cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2524a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2525cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityMultiViewport: 2526ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes pass &= require_feature(report_data, enabledFeatures.multiViewport, "multiViewport"); 2527cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2528a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 25297b6006f355aaacf7fc7f0d575b40285b89ecd279Chris Forbes case spv::CapabilityDrawParameters: 25307b6006f355aaacf7fc7f0d575b40285b89ecd279Chris Forbes pass &= require_extension(report_data, dev_data->device_extensions.khr_shader_draw_parameters_enabled, 25317b6006f355aaacf7fc7f0d575b40285b89ecd279Chris Forbes VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME); 25327b6006f355aaacf7fc7f0d575b40285b89ecd279Chris Forbes break; 25337b6006f355aaacf7fc7f0d575b40285b89ecd279Chris Forbes 25342664122d97c3f0a98b3e5d12833bbb20196ca837Mark Lobodzinski case spv::CapabilityGeometryShaderPassthroughNV: 25352664122d97c3f0a98b3e5d12833bbb20196ca837Mark Lobodzinski pass &= require_extension(report_data, dev_data->device_extensions.nv_geometry_shader_passthrough_enabled, 25362664122d97c3f0a98b3e5d12833bbb20196ca837Mark Lobodzinski VK_NV_GEOMETRY_SHADER_PASSTHROUGH_EXTENSION_NAME); 25372664122d97c3f0a98b3e5d12833bbb20196ca837Mark Lobodzinski break; 25382664122d97c3f0a98b3e5d12833bbb20196ca837Mark Lobodzinski 2539cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 2540436434eba4d9f91016f313c8fb1525d76d7932fcMark Lobodzinski // Spirv-validator should catch these errors 2541cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2542a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes } 2543a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes } 2544a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes } 2545a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2546a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes return pass; 2547a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes} 2548a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2549b2a61f3cd17c68887759817059fa1872f1e1464aChris Forbesstatic uint32_t descriptor_type_to_reqs(shader_module const *module, uint32_t type_id) { 25502aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes auto type = module->get_def(type_id); 25512aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes 25522aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes while (true) { 25532aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes switch (type.opcode()) { 2554cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeArray: 2555cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeSampledImage: 2556cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski type = module->get_def(type.word(2)); 2557cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2558cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypePointer: 2559cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski type = module->get_def(type.word(3)); 2560cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2561cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeImage: { 2562cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski auto dim = type.word(3); 2563cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski auto arrayed = type.word(5); 2564cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski auto msaa = type.word(6); 2565cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski 2566cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski switch (dim) { 2567cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::Dim1D: 2568cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return arrayed ? DESCRIPTOR_REQ_VIEW_TYPE_1D_ARRAY : DESCRIPTOR_REQ_VIEW_TYPE_1D; 2569cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::Dim2D: 2570cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return (msaa ? DESCRIPTOR_REQ_MULTI_SAMPLE : DESCRIPTOR_REQ_SINGLE_SAMPLE) | 2571cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski (arrayed ? DESCRIPTOR_REQ_VIEW_TYPE_2D_ARRAY : DESCRIPTOR_REQ_VIEW_TYPE_2D); 2572cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::Dim3D: 2573cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return DESCRIPTOR_REQ_VIEW_TYPE_3D; 2574cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::DimCube: 2575cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return arrayed ? DESCRIPTOR_REQ_VIEW_TYPE_CUBE_ARRAY : DESCRIPTOR_REQ_VIEW_TYPE_CUBE; 2576cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::DimSubpassData: 2577cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return msaa ? DESCRIPTOR_REQ_MULTI_SAMPLE : DESCRIPTOR_REQ_SINGLE_SAMPLE; 2578cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: // buffer, etc. 2579cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return 0; 2580cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 25812aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes } 2582cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 2583cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return 0; 25842aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes } 25852aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes } 2586b2a61f3cd17c68887759817059fa1872f1e1464aChris Forbes} 2587b2a61f3cd17c68887759817059fa1872f1e1464aChris Forbes 2588cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskistatic bool validate_pipeline_shader_stage( 2589ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes layer_data *dev_data, VkPipelineShaderStageCreateInfo const *pStage, PIPELINE_STATE *pipeline, 2590ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes shader_module **out_module, spirv_inst_iter *out_entrypoint) { 2591e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool pass = true; 2592ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes auto module_it = dev_data->shaderModuleMap.find(pStage->module); 259369f9a551bfb1fd5334950f9685c12c5adda23dfbChris Forbes auto module = *out_module = module_it->second.get(); 2594ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes auto report_data = dev_data->report_data; 259578be5018e238bd464b1f1c55138df277c0c18922Chris Forbes 2596c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski if (!module->has_valid_spirv) return pass; 2597c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski 259825002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Find the entrypoint 259978be5018e238bd464b1f1c55138df277c0c18922Chris Forbes auto entrypoint = *out_entrypoint = find_entrypoint(module, pStage->pName, pStage->stage); 260078be5018e238bd464b1f1c55138df277c0c18922Chris Forbes if (entrypoint == module->end()) { 2601ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, VALIDATION_ERROR_00510, 26024f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "SC", "No entrypoint found named `%s` for stage %s. %s.", pStage->pName, 26034f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes string_VkShaderStageFlagBits(pStage->stage), validation_error_map[VALIDATION_ERROR_00510])) { 2604cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return false; // no point continuing beyond here, any analysis is just going to be garbage. 260578be5018e238bd464b1f1c55138df277c0c18922Chris Forbes } 260678be5018e238bd464b1f1c55138df277c0c18922Chris Forbes } 260778be5018e238bd464b1f1c55138df277c0c18922Chris Forbes 260825002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Validate shader capabilities against enabled device features 2609ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes pass &= validate_shader_capabilities(dev_data, module); 261078be5018e238bd464b1f1c55138df277c0c18922Chris Forbes 261125002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Mark accessible ids 26123a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes auto accessible_ids = mark_accessible_ids(module, entrypoint); 261378be5018e238bd464b1f1c55138df277c0c18922Chris Forbes 261425002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Validate descriptor set layout against what the entrypoint actually uses 26153a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes auto descriptor_uses = collect_interface_by_descriptor_slot(report_data, module, accessible_ids); 261678be5018e238bd464b1f1c55138df277c0c18922Chris Forbes 26172e0eca3d6fad72a29ae072e3895e29a2d2d66476Tobin Ehlis auto pipelineLayout = pipeline->pipeline_layout; 2618ed399f66e0512ef077d0e0a7cb903248726d2424Chris Forbes 26190cfa9c3a1747749777581684536218f83c3977a9Chris Forbes pass &= validate_specialization_offsets(report_data, pStage); 2620416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis pass &= validate_push_constant_usage(report_data, &pipelineLayout.push_constant_ranges, module, accessible_ids, pStage->stage); 262178be5018e238bd464b1f1c55138df277c0c18922Chris Forbes 262225002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Validate descriptor use 262378be5018e238bd464b1f1c55138df277c0c18922Chris Forbes for (auto use : descriptor_uses) { 262478be5018e238bd464b1f1c55138df277c0c18922Chris Forbes // While validating shaders capture which slots are used by the pipeline 2625bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto &reqs = pipeline->active_slots[use.first.first][use.first.second]; 2626b2a61f3cd17c68887759817059fa1872f1e1464aChris Forbes reqs = descriptor_req(reqs | descriptor_type_to_reqs(module, use.second.type_id)); 262778be5018e238bd464b1f1c55138df277c0c18922Chris Forbes 262825002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Verify given pipelineLayout has requested setLayout with requested binding 2629c8268861aaa8f9c47920065d6323e4609e5081b0Tobin Ehlis const auto &binding = get_descriptor_binding(&pipelineLayout, use.first); 263078be5018e238bd464b1f1c55138df277c0c18922Chris Forbes unsigned required_descriptor_count; 263178be5018e238bd464b1f1c55138df277c0c18922Chris Forbes 263278be5018e238bd464b1f1c55138df277c0c18922Chris Forbes if (!binding) { 2633bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 2634bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SHADER_CHECKER_MISSING_DESCRIPTOR, "SC", 263578be5018e238bd464b1f1c55138df277c0c18922Chris Forbes "Shader uses descriptor slot %u.%u (used as type `%s`) but not declared in pipeline layout", 263678be5018e238bd464b1f1c55138df277c0c18922Chris Forbes use.first.first, use.first.second, describe_type(module, use.second.type_id).c_str())) { 2637e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves pass = false; 263878be5018e238bd464b1f1c55138df277c0c18922Chris Forbes } 263978be5018e238bd464b1f1c55138df277c0c18922Chris Forbes } else if (~binding->stageFlags & pStage->stage) { 2640bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 0, __LINE__, 2641cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski SHADER_CHECKER_DESCRIPTOR_NOT_ACCESSIBLE_FROM_STAGE, "SC", 2642cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Shader uses descriptor slot %u.%u (used " 2643cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "as type `%s`) but descriptor not " 2644cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "accessible from stage %s", 2645fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis use.first.first, use.first.second, describe_type(module, use.second.type_id).c_str(), 264678be5018e238bd464b1f1c55138df277c0c18922Chris Forbes string_VkShaderStageFlagBits(pStage->stage))) { 2647e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves pass = false; 264878be5018e238bd464b1f1c55138df277c0c18922Chris Forbes } 2649bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski } else if (!descriptor_type_match(module, use.second.type_id, binding->descriptorType, required_descriptor_count)) { 2650557cdd5218accf51ca894a14b7c6eeeb733f5cbbChris Forbes if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 2651cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski SHADER_CHECKER_DESCRIPTOR_TYPE_MISMATCH, "SC", 2652cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Type mismatch on descriptor slot " 2653cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%u.%u (used as type `%s`) but " 2654cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "descriptor of type %s", 2655fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis use.first.first, use.first.second, describe_type(module, use.second.type_id).c_str(), 265678be5018e238bd464b1f1c55138df277c0c18922Chris Forbes string_VkDescriptorType(binding->descriptorType))) { 2657e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves pass = false; 265878be5018e238bd464b1f1c55138df277c0c18922Chris Forbes } 265978be5018e238bd464b1f1c55138df277c0c18922Chris Forbes } else if (binding->descriptorCount < required_descriptor_count) { 2660557cdd5218accf51ca894a14b7c6eeeb733f5cbbChris Forbes if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 2661fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis SHADER_CHECKER_DESCRIPTOR_TYPE_MISMATCH, "SC", 266278be5018e238bd464b1f1c55138df277c0c18922Chris Forbes "Shader expects at least %u descriptors for binding %u.%u (used as type `%s`) but only %u provided", 266378be5018e238bd464b1f1c55138df277c0c18922Chris Forbes required_descriptor_count, use.first.first, use.first.second, 2664fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis describe_type(module, use.second.type_id).c_str(), binding->descriptorCount)) { 2665e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves pass = false; 266678be5018e238bd464b1f1c55138df277c0c18922Chris Forbes } 266778be5018e238bd464b1f1c55138df277c0c18922Chris Forbes } 266878be5018e238bd464b1f1c55138df277c0c18922Chris Forbes } 266978be5018e238bd464b1f1c55138df277c0c18922Chris Forbes 267025002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Validate use of input attachments against subpass structure 2671c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes if (pStage->stage == VK_SHADER_STAGE_FRAGMENT_BIT) { 26723a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes auto input_attachment_uses = collect_interface_by_input_attachment_index(report_data, module, accessible_ids); 2673c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes 2674c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes auto rpci = pipeline->render_pass_ci.ptr(); 2675c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes auto subpass = pipeline->graphicsPipelineCI.subpass; 2676c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes 2677c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes for (auto use : input_attachment_uses) { 2678c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes auto input_attachments = rpci->pSubpasses[subpass].pInputAttachments; 2679bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto index = (input_attachments && use.first < rpci->pSubpasses[subpass].inputAttachmentCount) 2680bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski ? input_attachments[use.first].attachment 2681bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski : VK_ATTACHMENT_UNUSED; 2682c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes 2683c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes if (index == VK_ATTACHMENT_UNUSED) { 2684c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 2685c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes SHADER_CHECKER_MISSING_INPUT_ATTACHMENT, "SC", 2686bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "Shader consumes input attachment index %d but not provided in subpass", use.first)) { 2687c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes pass = false; 2688c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes } 2689f0fdde7692ffd5175435cc3bf3412b8468054f38Chris Forbes } else if (!(get_format_type(rpci->pAttachments[index].format) & get_fundamental_type(module, use.second.type_id))) { 2690eeb9f6a27f1acc11e54080fb3bcda7b513b5c89fChris Forbes if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 2691eeb9f6a27f1acc11e54080fb3bcda7b513b5c89fChris Forbes SHADER_CHECKER_INPUT_ATTACHMENT_TYPE_MISMATCH, "SC", 2692bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "Subpass input attachment %u format of %s does not match type used in shader `%s`", use.first, 2693bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski string_VkFormat(rpci->pAttachments[index].format), describe_type(module, use.second.type_id).c_str())) { 2694eeb9f6a27f1acc11e54080fb3bcda7b513b5c89fChris Forbes pass = false; 2695eeb9f6a27f1acc11e54080fb3bcda7b513b5c89fChris Forbes } 2696eeb9f6a27f1acc11e54080fb3bcda7b513b5c89fChris Forbes } 2697c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes } 2698c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes } 2699c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes 270078be5018e238bd464b1f1c55138df277c0c18922Chris Forbes return pass; 270178be5018e238bd464b1f1c55138df277c0c18922Chris Forbes} 270278be5018e238bd464b1f1c55138df277c0c18922Chris Forbes 2703a61b537fcb6a4f7b92cd217b3964ad7a48109da1Tobin Ehlis// Validate that the shaders used by the given pipeline and store the active_slots 2704a61b537fcb6a4f7b92cd217b3964ad7a48109da1Tobin Ehlis// that are actually used by the pipeline into pPipeline->active_slots 2705ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbesstatic bool validate_and_capture_pipeline_shader_state(layer_data *dev_data, PIPELINE_STATE *pPipeline) { 27066660d6f3e4e4c895063e8d99098162bd2f508b24Chris Forbes auto pCreateInfo = pPipeline->graphicsPipelineCI.ptr(); 27075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis int vertex_stage = get_shader_stage_id(VK_SHADER_STAGE_VERTEX_BIT); 27085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis int fragment_stage = get_shader_stage_id(VK_SHADER_STAGE_FRAGMENT_BIT); 27095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 27105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis shader_module *shaders[5]; 27115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis memset(shaders, 0, sizeof(shaders)); 27125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis spirv_inst_iter entrypoints[5]; 27135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis memset(entrypoints, 0, sizeof(entrypoints)); 2714e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool pass = true; 27155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 27165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->stageCount; i++) { 27176660d6f3e4e4c895063e8d99098162bd2f508b24Chris Forbes auto pStage = &pCreateInfo->pStages[i]; 271878be5018e238bd464b1f1c55138df277c0c18922Chris Forbes auto stage_id = get_shader_stage_id(pStage->stage); 2719ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes pass &= validate_pipeline_shader_stage(dev_data, pStage, pPipeline, &shaders[stage_id], &entrypoints[stage_id]); 27205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 27215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2722d5365427feb4a6c16371ecb651afa37b89dabd96Chris Forbes // if the shader stages are no good individually, cross-stage validation is pointless. 2723cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!pass) return false; 2724b7476f4c4998ae20e579bd2d134667b71acdbf91Chris Forbes 2725ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes auto vi = pCreateInfo->pVertexInputState; 27265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 27275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (vi) { 2728ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes pass &= validate_vi_consistency(dev_data->report_data, vi); 27295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 27305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2731c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski if (shaders[vertex_stage] && shaders[vertex_stage]->has_valid_spirv) { 2732ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes pass &= validate_vi_against_vs_inputs(dev_data->report_data, vi, shaders[vertex_stage], entrypoints[vertex_stage]); 27335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 27345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 27355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis int producer = get_shader_stage_id(VK_SHADER_STAGE_VERTEX_BIT); 27365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis int consumer = get_shader_stage_id(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT); 27375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 27385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis while (!shaders[producer] && producer != fragment_stage) { 27395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis producer++; 27405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis consumer++; 27415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 27425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 27435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (; producer != fragment_stage && consumer <= fragment_stage; consumer++) { 27445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(shaders[producer]); 2745c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski if (shaders[consumer] && shaders[consumer]->has_valid_spirv && shaders[producer]->has_valid_spirv) { 2746ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes pass &= validate_interface_between_stages(dev_data->report_data, shaders[producer], entrypoints[producer], 2747bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &shader_stage_attribs[producer], shaders[consumer], entrypoints[consumer], 2748bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &shader_stage_attribs[consumer]); 27495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 27505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis producer = consumer; 27515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 27525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 27535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2754c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski if (shaders[fragment_stage] && shaders[fragment_stage]->has_valid_spirv) { 2755ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes pass &= validate_fs_outputs_against_render_pass(dev_data->report_data, shaders[fragment_stage], entrypoints[fragment_stage], 27568da1edac0fbed13831b2f458f27c51e64d6210ffTobin Ehlis pPipeline->render_pass_ci.ptr(), pCreateInfo->subpass); 27575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 27585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 27595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return pass; 27605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 27615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2762ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbesstatic bool validate_compute_pipeline(layer_data *dev_data, PIPELINE_STATE *pPipeline) { 27636660d6f3e4e4c895063e8d99098162bd2f508b24Chris Forbes auto pCreateInfo = pPipeline->computePipelineCI.ptr(); 276403857e826cdc6e8d814137fb3245596ca1cb7bc7Chris Forbes 276503857e826cdc6e8d814137fb3245596ca1cb7bc7Chris Forbes shader_module *module; 276603857e826cdc6e8d814137fb3245596ca1cb7bc7Chris Forbes spirv_inst_iter entrypoint; 276703857e826cdc6e8d814137fb3245596ca1cb7bc7Chris Forbes 2768ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes return validate_pipeline_shader_stage(dev_data, &pCreateInfo->stage, pPipeline, &module, &entrypoint); 276903857e826cdc6e8d814137fb3245596ca1cb7bc7Chris Forbes} 27705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Return Set node ptr for specified set or else NULL 27719a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehliscvdescriptorset::DescriptorSet *GetSetNode(const layer_data *dev_data, VkDescriptorSet set) { 277251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis auto set_it = dev_data->setMap.find(set); 277351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (set_it == dev_data->setMap.end()) { 27745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return NULL; 27755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 2776104ab082916e41467ef60baaab7a5a8b2e02c59cTobin Ehlis return set_it->second; 27775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 27785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2779eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young// For given pipeline, return number of MSAA samples, or one if MSAA disabled 27804c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlisstatic VkSampleCountFlagBits getNumSamples(PIPELINE_STATE const *pipe) { 2781ea8349eeee76ae2859c10870fd8bd9e60309eb28Chris Forbes if (pipe->graphicsPipelineCI.pMultisampleState != NULL && 2782ea8349eeee76ae2859c10870fd8bd9e60309eb28Chris Forbes VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO == pipe->graphicsPipelineCI.pMultisampleState->sType) { 2783eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young return pipe->graphicsPipelineCI.pMultisampleState->rasterizationSamples; 2784eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young } 2785eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young return VK_SAMPLE_COUNT_1_BIT; 2786eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young} 2787eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young 2788bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic void list_bits(std::ostream &s, uint32_t bits) { 2789b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes for (int i = 0; i < 32 && bits; i++) { 2790b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes if (bits & (1 << i)) { 2791b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes s << i; 2792b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes bits &= ~(1 << i); 2793b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes if (bits) { 2794b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes s << ","; 2795b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes } 2796b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes } 2797b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes } 2798b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes} 2799b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes 2800eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young// Validate draw-time state related to the PSO 280151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool ValidatePipelineDrawtimeState(layer_data const *dev_data, LAST_BOUND_STATE const &state, const GLOBAL_CB_NODE *pCB, 28024c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis PIPELINE_STATE const *pPipeline) { 2803eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young bool skip_call = false; 280429d196e071b2dc1db47702085469396f2b956820Chris Forbes 2805d79335137b414d5f89284a9ab3e014beb4ada3ebMike Weiblen // Verify vertex binding 280629d196e071b2dc1db47702085469396f2b956820Chris Forbes if (pPipeline->vertexBindingDescriptions.size() > 0) { 280729d196e071b2dc1db47702085469396f2b956820Chris Forbes for (size_t i = 0; i < pPipeline->vertexBindingDescriptions.size(); i++) { 2808312129ec52e6249aa453e27e6be17a8dab1e98b8Tobin Ehlis auto vertex_binding = pPipeline->vertexBindingDescriptions[i].binding; 2809312129ec52e6249aa453e27e6be17a8dab1e98b8Tobin Ehlis if ((pCB->currentDrawData.buffers.size() < (vertex_binding + 1)) || 2810312129ec52e6249aa453e27e6be17a8dab1e98b8Tobin Ehlis (pCB->currentDrawData.buffers[vertex_binding] == VK_NULL_HANDLE)) { 2811cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski skip_call |= 2812df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 2813df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(pCB->commandBuffer), __LINE__, DRAWSTATE_VTX_INDEX_OUT_OF_BOUNDS, "DS", 2814cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "The Pipeline State Object (0x%" PRIxLEAST64 2815cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ") expects that this Command Buffer's vertex binding Index %u " 2816cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "should be set via vkCmdBindVertexBuffers. This is because VkVertexInputBindingDescription struct " 2817cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "at index " PRINTF_SIZE_T_SPECIFIER " of pVertexBindingDescriptions has a binding value of %u.", 2818cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski (uint64_t)state.pipeline_state->pipeline, vertex_binding, i, vertex_binding); 281929d196e071b2dc1db47702085469396f2b956820Chris Forbes } 282029d196e071b2dc1db47702085469396f2b956820Chris Forbes } 282129d196e071b2dc1db47702085469396f2b956820Chris Forbes } else { 282258b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis if (!pCB->currentDrawData.buffers.empty() && !pCB->vertex_buffer_used) { 2823df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, 2824df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t>(pCB->commandBuffer), 2825df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski __LINE__, DRAWSTATE_VTX_INDEX_OUT_OF_BOUNDS, "DS", 2826226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "Vertex buffers are bound to command buffer (0x%p" 28275c288f35b2eab0dab95d18768235fef6ffd69b30Tobin Ehlis ") but no vertex buffers are attached to this Pipeline State Object (0x%" PRIxLEAST64 ").", 2828226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis pCB->commandBuffer, (uint64_t)state.pipeline_state->pipeline); 282929d196e071b2dc1db47702085469396f2b956820Chris Forbes } 283029d196e071b2dc1db47702085469396f2b956820Chris Forbes } 283129d196e071b2dc1db47702085469396f2b956820Chris Forbes // If Viewport or scissors are dynamic, verify that dynamic count matches PSO count. 283229d196e071b2dc1db47702085469396f2b956820Chris Forbes // Skip check if rasterization is disabled or there is no viewport. 283329d196e071b2dc1db47702085469396f2b956820Chris Forbes if ((!pPipeline->graphicsPipelineCI.pRasterizationState || 283429d196e071b2dc1db47702085469396f2b956820Chris Forbes (pPipeline->graphicsPipelineCI.pRasterizationState->rasterizerDiscardEnable == VK_FALSE)) && 283529d196e071b2dc1db47702085469396f2b956820Chris Forbes pPipeline->graphicsPipelineCI.pViewportState) { 283629d196e071b2dc1db47702085469396f2b956820Chris Forbes bool dynViewport = isDynamic(pPipeline, VK_DYNAMIC_STATE_VIEWPORT); 283729d196e071b2dc1db47702085469396f2b956820Chris Forbes bool dynScissor = isDynamic(pPipeline, VK_DYNAMIC_STATE_SCISSOR); 2838b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes 283929d196e071b2dc1db47702085469396f2b956820Chris Forbes if (dynViewport) { 2840b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes auto requiredViewportsMask = (1 << pPipeline->graphicsPipelineCI.pViewportState->viewportCount) - 1; 2841b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes auto missingViewportMask = ~pCB->viewportMask & requiredViewportsMask; 2842b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes if (missingViewportMask) { 2843b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes std::stringstream ss; 2844b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes ss << "Dynamic viewport(s) "; 2845b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes list_bits(ss, missingViewportMask); 2846d79335137b414d5f89284a9ab3e014beb4ada3ebMike Weiblen ss << " are used by pipeline state object, but were not provided via calls to vkCmdSetViewport()."; 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 } 2851b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes 285229d196e071b2dc1db47702085469396f2b956820Chris Forbes if (dynScissor) { 2853b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes auto requiredScissorMask = (1 << pPipeline->graphicsPipelineCI.pViewportState->scissorCount) - 1; 2854b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes auto missingScissorMask = ~pCB->scissorMask & requiredScissorMask; 2855b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes if (missingScissorMask) { 2856b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes std::stringstream ss; 2857b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes ss << "Dynamic scissor(s) "; 2858b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes list_bits(ss, missingScissorMask); 2859d79335137b414d5f89284a9ab3e014beb4ada3ebMike Weiblen ss << " are used by pipeline state object, but were not provided via calls to vkCmdSetScissor()."; 286051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, 2861bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski __LINE__, DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS", "%s", ss.str().c_str()); 286229d196e071b2dc1db47702085469396f2b956820Chris Forbes } 286329d196e071b2dc1db47702085469396f2b956820Chris Forbes } 286429d196e071b2dc1db47702085469396f2b956820Chris Forbes } 286529d196e071b2dc1db47702085469396f2b956820Chris Forbes 286629d196e071b2dc1db47702085469396f2b956820Chris Forbes // Verify that any MSAA request in PSO matches sample# in bound FB 286729d196e071b2dc1db47702085469396f2b956820Chris Forbes // Skip the check if rasterization is disabled. 286829d196e071b2dc1db47702085469396f2b956820Chris Forbes if (!pPipeline->graphicsPipelineCI.pRasterizationState || 286929d196e071b2dc1db47702085469396f2b956820Chris Forbes (pPipeline->graphicsPipelineCI.pRasterizationState->rasterizerDiscardEnable == VK_FALSE)) { 287029d196e071b2dc1db47702085469396f2b956820Chris Forbes VkSampleCountFlagBits pso_num_samples = getNumSamples(pPipeline); 287129d196e071b2dc1db47702085469396f2b956820Chris Forbes if (pCB->activeRenderPass) { 2872fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes auto const render_pass_info = pCB->activeRenderPass->createInfo.ptr(); 287329d196e071b2dc1db47702085469396f2b956820Chris Forbes const VkSubpassDescription *subpass_desc = &render_pass_info->pSubpasses[pCB->activeSubpass]; 287429d196e071b2dc1db47702085469396f2b956820Chris Forbes uint32_t i; 287576957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes unsigned subpass_num_samples = 0; 28760a7ed0466d3d3c6c71be07d66c200482d9a9d073Chris Forbes 287729d196e071b2dc1db47702085469396f2b956820Chris Forbes for (i = 0; i < subpass_desc->colorAttachmentCount; i++) { 287876957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes auto attachment = subpass_desc->pColorAttachments[i].attachment; 287976957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes if (attachment != VK_ATTACHMENT_UNUSED) 288076957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes subpass_num_samples |= (unsigned)render_pass_info->pAttachments[attachment].samples; 288129d196e071b2dc1db47702085469396f2b956820Chris Forbes } 28820a7ed0466d3d3c6c71be07d66c200482d9a9d073Chris Forbes 288376957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes if (subpass_desc->pDepthStencilAttachment && 288476957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes subpass_desc->pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) { 288576957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes auto attachment = subpass_desc->pDepthStencilAttachment->attachment; 288676957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes subpass_num_samples |= (unsigned)render_pass_info->pAttachments[attachment].samples; 288729d196e071b2dc1db47702085469396f2b956820Chris Forbes } 2888eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young 28890dc3fd4e57b8531638781daa01a2fb5d1048a6fbJamie Madill if (subpass_num_samples && static_cast<unsigned>(pso_num_samples) != subpass_num_samples) { 289029d196e071b2dc1db47702085469396f2b956820Chris Forbes skip_call |= 289151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 2892bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski reinterpret_cast<const uint64_t &>(pPipeline->pipeline), __LINE__, DRAWSTATE_NUM_SAMPLES_MISMATCH, "DS", 2893bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "Num samples mismatch! At draw-time in Pipeline (0x%" PRIxLEAST64 2894bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski ") with %u samples while current RenderPass (0x%" PRIxLEAST64 ") w/ %u samples!", 2895bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski reinterpret_cast<const uint64_t &>(pPipeline->pipeline), pso_num_samples, 2896bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski reinterpret_cast<const uint64_t &>(pCB->activeRenderPass->renderPass), subpass_num_samples); 2897eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young } 289829d196e071b2dc1db47702085469396f2b956820Chris Forbes } else { 289951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 2900bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski reinterpret_cast<const uint64_t &>(pPipeline->pipeline), __LINE__, DRAWSTATE_NUM_SAMPLES_MISMATCH, 2901bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "DS", "No active render pass found at draw-time in Pipeline (0x%" PRIxLEAST64 ")!", 290229d196e071b2dc1db47702085469396f2b956820Chris Forbes reinterpret_cast<const uint64_t &>(pPipeline->pipeline)); 2903eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young } 2904eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young } 2905528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis // Verify that PSO creation renderPass is compatible with active renderPass 2906528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis if (pCB->activeRenderPass) { 2907528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis std::string err_string; 2908a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis if ((pCB->activeRenderPass->renderPass != pPipeline->graphicsPipelineCI.renderPass) && 290951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis !verify_renderpass_compatibility(dev_data, pCB->activeRenderPass->createInfo.ptr(), pPipeline->render_pass_ci.ptr(), 2910528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis err_string)) { 2911528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis // renderPass that PSO was created with must be compatible with active renderPass that PSO is being used with 2912528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis skip_call |= 291351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 2914528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis reinterpret_cast<const uint64_t &>(pPipeline->pipeline), __LINE__, DRAWSTATE_RENDERPASS_INCOMPATIBLE, "DS", 2915cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "At Draw time the active render pass (0x%" PRIxLEAST64 2916cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ") is incompatible w/ gfx pipeline " 2917528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis "(0x%" PRIxLEAST64 ") that was created w/ render pass (0x%" PRIxLEAST64 ") due to: %s", 29186de0e43adfbd3c049252412d998524e7edbd3796Chris Forbes reinterpret_cast<uint64_t &>(pCB->activeRenderPass->renderPass), 29196de0e43adfbd3c049252412d998524e7edbd3796Chris Forbes reinterpret_cast<uint64_t const &>(pPipeline->pipeline), 2920528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis reinterpret_cast<const uint64_t &>(pPipeline->graphicsPipelineCI.renderPass), err_string.c_str()); 2921528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis } 2922c307df2953e6b023531a6ef7fd11e3ee2f2c58b0Chris Forbes 2923c307df2953e6b023531a6ef7fd11e3ee2f2c58b0Chris Forbes if (pPipeline->graphicsPipelineCI.subpass != pCB->activeSubpass) { 2924c307df2953e6b023531a6ef7fd11e3ee2f2c58b0Chris Forbes skip_call |= 292551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 2926c307df2953e6b023531a6ef7fd11e3ee2f2c58b0Chris Forbes reinterpret_cast<uint64_t const &>(pPipeline->pipeline), __LINE__, DRAWSTATE_RENDERPASS_INCOMPATIBLE, "DS", 2927c307df2953e6b023531a6ef7fd11e3ee2f2c58b0Chris Forbes "Pipeline was built for subpass %u but used in subpass %u", pPipeline->graphicsPipelineCI.subpass, 2928c307df2953e6b023531a6ef7fd11e3ee2f2c58b0Chris Forbes pCB->activeSubpass); 2929c307df2953e6b023531a6ef7fd11e3ee2f2c58b0Chris Forbes } 2930528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis } 293129d196e071b2dc1db47702085469396f2b956820Chris Forbes // TODO : Add more checks here 293229d196e071b2dc1db47702085469396f2b956820Chris Forbes 2933eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young return skip_call; 2934eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young} 2935eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young 29365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Validate overall state at the time of a draw call 293751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool ValidateDrawState(layer_data *dev_data, GLOBAL_CB_NODE *cb_node, const bool indexed, 29384f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes const VkPipelineBindPoint bind_point, const char *function, 29394f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes UNIQUE_VALIDATION_ERROR_CODE const msg_code) { 2940e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool result = false; 29411c130ea631a82716dc7334de17767536525f2292Tobin Ehlis auto const &state = cb_node->lastBound[bind_point]; 29424c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis PIPELINE_STATE *pPipe = state.pipeline_state; 294322fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis if (nullptr == pPipe) { 294422fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis result |= log_msg( 2945df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 2946df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, DRAWSTATE_INVALID_PIPELINE, "DS", 294722fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis "At Draw/Dispatch time no valid VkPipeline is bound! This is illegal. Please bind one with vkCmdBindPipeline()."); 294822fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis // Early return as any further checks below will be busted w/o a pipeline 2949cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (result) return true; 295022fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis } 29513d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis // First check flag states 29521c130ea631a82716dc7334de17767536525f2292Tobin Ehlis if (VK_PIPELINE_BIND_POINT_GRAPHICS == bind_point) 295351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis result = validate_draw_state_flags(dev_data, cb_node, pPipe, indexed, msg_code); 29547a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis 29555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Now complete other state checks 295669b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis if (VK_NULL_HANDLE != state.pipeline_layout.layout) { 295722fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis string errorString; 295869b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis auto pipeline_layout = pPipe->pipeline_layout; 2959169c4506062f06d6676eb4da3c9e0437d1d9d659Chris Forbes 29601c130ea631a82716dc7334de17767536525f2292Tobin Ehlis for (const auto &set_binding_pair : pPipe->active_slots) { 29611c130ea631a82716dc7334de17767536525f2292Tobin Ehlis uint32_t setIndex = set_binding_pair.first; 296222fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis // If valid set is not bound throw an error 296322fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis if ((state.boundDescriptorSets.size() <= setIndex) || (!state.boundDescriptorSets[setIndex])) { 2964df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski result |= log_msg( 2965df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 2966df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, DRAWSTATE_DESCRIPTOR_SET_NOT_BOUND, "DS", 2967df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "VkPipeline 0x%" PRIxLEAST64 " uses set #%u but that set is not bound.", (uint64_t)pPipe->pipeline, setIndex); 296851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis } else if (!verify_set_layout_compatibility(dev_data, state.boundDescriptorSets[setIndex], &pipeline_layout, setIndex, 296969b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis errorString)) { 297069b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis // Set is bound but not compatible w/ overlapping pipeline_layout from PSO 297171511c5a10533c910bfe62c3bcf58e2a4054e7acTobin Ehlis VkDescriptorSet setHandle = state.boundDescriptorSets[setIndex]->GetSet(); 297222fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis result |= 297351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, 297422fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis (uint64_t)setHandle, __LINE__, DRAWSTATE_PIPELINE_LAYOUTS_INCOMPATIBLE, "DS", 2975414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller "VkDescriptorSet (0x%" PRIxLEAST64 2976414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller ") bound as set #%u is not compatible with overlapping VkPipelineLayout 0x%" PRIxLEAST64 " due to: %s", 297769b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis reinterpret_cast<uint64_t &>(setHandle), setIndex, reinterpret_cast<uint64_t &>(pipeline_layout.layout), 297869b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis errorString.c_str()); 2979cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else { // Valid set is bound and layout compatible, validate that it's updated 298022fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis // Pull the set node 29811c130ea631a82716dc7334de17767536525f2292Tobin Ehlis cvdescriptorset::DescriptorSet *descriptor_set = state.boundDescriptorSets[setIndex]; 2982aa21bc3b3c5c7adfeb488fc80bdcb339d63615b8Tobin Ehlis // Gather active bindings 2983ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis std::unordered_set<uint32_t> active_bindings; 29841c130ea631a82716dc7334de17767536525f2292Tobin Ehlis for (auto binding : set_binding_pair.second) { 2985ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis active_bindings.insert(binding.first); 2986aa21bc3b3c5c7adfeb488fc80bdcb339d63615b8Tobin Ehlis } 298722fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis // Make sure set has been updated if it has no immutable samplers 298822fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis // If it has immutable samplers, we'll flag error later as needed depending on binding 29891c130ea631a82716dc7334de17767536525f2292Tobin Ehlis if (!descriptor_set->IsUpdated()) { 2990ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis for (auto binding : active_bindings) { 29911c130ea631a82716dc7334de17767536525f2292Tobin Ehlis if (!descriptor_set->GetImmutableSamplerPtrFromBinding(binding)) { 299251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis result |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 2993cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t)descriptor_set->GetSet(), 2994cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, DRAWSTATE_DESCRIPTOR_SET_NOT_UPDATED, "DS", 2995cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Descriptor Set 0x%" PRIxLEAST64 2996cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " bound but was never updated. It is now being used to draw so " 2997cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "this will result in undefined behavior.", 2998cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski (uint64_t)descriptor_set->GetSet()); 2999fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis } 30005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 30015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 30027433ab60c7ff16d37edb0f8b17b606ccd363e210Tobin Ehlis // Validate the draw-time state for this descriptor set 30037433ab60c7ff16d37edb0f8b17b606ccd363e210Tobin Ehlis std::string err_str; 30041c130ea631a82716dc7334de17767536525f2292Tobin Ehlis if (!descriptor_set->ValidateDrawState(set_binding_pair.second, state.dynamicOffsets[setIndex], &err_str)) { 30051c130ea631a82716dc7334de17767536525f2292Tobin Ehlis auto set = descriptor_set->GetSet(); 300651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis result |= log_msg( 300751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, 300851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis reinterpret_cast<const uint64_t &>(set), __LINE__, DRAWSTATE_DESCRIPTOR_SET_NOT_UPDATED, "DS", 300951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis "Descriptor set 0x%" PRIxLEAST64 " encountered the following validation error at %s() time: %s", 301051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis reinterpret_cast<const uint64_t &>(set), function, err_str.c_str()); 30117433ab60c7ff16d37edb0f8b17b606ccd363e210Tobin Ehlis } 30125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 301322fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis } 301422fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis } 3015eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young 3016eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young // Check general pipeline state that needs to be validated at drawtime 301751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (VK_PIPELINE_BIND_POINT_GRAPHICS == bind_point) result |= ValidatePipelineDrawtimeState(dev_data, state, cb_node, pPipe); 3018eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young 30195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 30205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 30215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 302251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic void UpdateDrawState(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, const VkPipelineBindPoint bind_point) { 30231c130ea631a82716dc7334de17767536525f2292Tobin Ehlis auto const &state = cb_state->lastBound[bind_point]; 3024ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis PIPELINE_STATE *pPipe = state.pipeline_state; 3025ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis if (VK_NULL_HANDLE != state.pipeline_layout.layout) { 30261c130ea631a82716dc7334de17767536525f2292Tobin Ehlis for (const auto &set_binding_pair : pPipe->active_slots) { 30271c130ea631a82716dc7334de17767536525f2292Tobin Ehlis uint32_t setIndex = set_binding_pair.first; 3028ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis // Pull the set node 30291c130ea631a82716dc7334de17767536525f2292Tobin Ehlis cvdescriptorset::DescriptorSet *descriptor_set = state.boundDescriptorSets[setIndex]; 3030ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis // Bind this set and its active descriptor resources to the command buffer 30311c130ea631a82716dc7334de17767536525f2292Tobin Ehlis descriptor_set->BindCommandBuffer(cb_state, set_binding_pair.second); 30327433ab60c7ff16d37edb0f8b17b606ccd363e210Tobin Ehlis // For given active slots record updated images & buffers 30331c130ea631a82716dc7334de17767536525f2292Tobin Ehlis descriptor_set->GetStorageUpdates(set_binding_pair.second, &cb_state->updateBuffers, &cb_state->updateImages); 3034ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis } 3035ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis } 303658b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis if (pPipe->vertexBindingDescriptions.size() > 0) { 303758b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis cb_state->vertex_buffer_used = true; 303858b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis } 3039ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis} 3040ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis 3041a27508babf63d50aea75883a3702979193c23683Mark Young// Validate HW line width capabilities prior to setting requested line width. 3042df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinskistatic bool verifyLineWidth(layer_data *dev_data, DRAW_STATE_ERROR dsError, VkDebugReportObjectTypeEXT object_type, 3043df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski const uint64_t &target, float lineWidth) { 3044a27508babf63d50aea75883a3702979193c23683Mark Young bool skip_call = false; 3045a27508babf63d50aea75883a3702979193c23683Mark Young 3046a27508babf63d50aea75883a3702979193c23683Mark Young // First check to see if the physical device supports wide lines. 304751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if ((VK_FALSE == dev_data->enabled_features.wideLines) && (1.0f != lineWidth)) { 3048df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, object_type, target, __LINE__, dsError, "DS", 3049cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Attempt to set lineWidth to %f but physical device wideLines feature " 3050cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "not supported/enabled so lineWidth must be 1.0f!", 3051a27508babf63d50aea75883a3702979193c23683Mark Young lineWidth); 3052a27508babf63d50aea75883a3702979193c23683Mark Young } else { 3053a27508babf63d50aea75883a3702979193c23683Mark Young // Otherwise, make sure the width falls in the valid range. 305451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if ((dev_data->phys_dev_properties.properties.limits.lineWidthRange[0] > lineWidth) || 305551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis (dev_data->phys_dev_properties.properties.limits.lineWidthRange[1] < lineWidth)) { 3056df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, object_type, target, __LINE__, dsError, "DS", 3057cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Attempt to set lineWidth to %f but physical device limits line width " 3058cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "to between [%f, %f]!", 305951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis lineWidth, dev_data->phys_dev_properties.properties.limits.lineWidthRange[0], 306051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->phys_dev_properties.properties.limits.lineWidthRange[1]); 3061a27508babf63d50aea75883a3702979193c23683Mark Young } 3062a27508babf63d50aea75883a3702979193c23683Mark Young } 3063a27508babf63d50aea75883a3702979193c23683Mark Young 3064a27508babf63d50aea75883a3702979193c23683Mark Young return skip_call; 3065a27508babf63d50aea75883a3702979193c23683Mark Young} 3066a27508babf63d50aea75883a3702979193c23683Mark Young 30675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Verify that create state for a pipeline is valid 306851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool verifyPipelineCreateState(layer_data *dev_data, std::vector<PIPELINE_STATE *> pPipelines, int pipelineIndex) { 306983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 30705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 30714c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis PIPELINE_STATE *pPipeline = pPipelines[pipelineIndex]; 30725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 30735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // If create derivative bit is set, check that we've specified a base 30745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // pipeline correctly, and that the base pipeline was created to allow 30755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // derivatives. 30765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pPipeline->graphicsPipelineCI.flags & VK_PIPELINE_CREATE_DERIVATIVE_BIT) { 30774c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis PIPELINE_STATE *pBasePipeline = nullptr; 30785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!((pPipeline->graphicsPipelineCI.basePipelineHandle != VK_NULL_HANDLE) ^ 30795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (pPipeline->graphicsPipelineCI.basePipelineIndex != -1))) { 3080f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt // This check is a superset of VALIDATION_ERROR_00526 and VALIDATION_ERROR_00528 3081df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= 3082df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 3083df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t &>(pPipeline->pipeline), __LINE__, DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS", 3084df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "Invalid Pipeline CreateInfo: exactly one of base pipeline index and handle must be specified"); 30855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (pPipeline->graphicsPipelineCI.basePipelineIndex != -1) { 30865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pPipeline->graphicsPipelineCI.basePipelineIndex >= pipelineIndex) { 308783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= 3088df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 3089df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t &>(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_00518, "DS", 3090f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt "Invalid Pipeline CreateInfo: base pipeline must occur earlier in array than derivative pipeline. %s", 3091f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt validation_error_map[VALIDATION_ERROR_00518]); 30925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 30935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pBasePipeline = pPipelines[pPipeline->graphicsPipelineCI.basePipelineIndex]; 30945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 30955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (pPipeline->graphicsPipelineCI.basePipelineHandle != VK_NULL_HANDLE) { 309651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis pBasePipeline = getPipelineState(dev_data, pPipeline->graphicsPipelineCI.basePipelineHandle); 30975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 30985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 30995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pBasePipeline && !(pBasePipeline->graphicsPipelineCI.flags & VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT)) { 3100df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= 3101df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 3102df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t &>(pPipeline->pipeline), __LINE__, DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS", 3103df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "Invalid Pipeline CreateInfo: base pipeline does not allow derivatives."); 31045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 31055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 31065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 31075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pPipeline->graphicsPipelineCI.pColorBlendState != NULL) { 3108fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis const safe_VkPipelineColorBlendStateCreateInfo *color_blend_state = pPipeline->graphicsPipelineCI.pColorBlendState; 31099a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto const render_pass_info = GetRenderPassState(dev_data, pPipeline->graphicsPipelineCI.renderPass)->createInfo.ptr(); 3110fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis const VkSubpassDescription *subpass_desc = &render_pass_info->pSubpasses[pPipeline->graphicsPipelineCI.subpass]; 3111fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis if (color_blend_state->attachmentCount != subpass_desc->colorAttachmentCount) { 3112fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis skip_call |= log_msg( 311351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 3114fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis reinterpret_cast<const uint64_t &>(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_02109, "DS", 3115fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis "vkCreateGraphicsPipelines(): Render pass (0x%" PRIxLEAST64 3116fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis ") subpass %u has colorAttachmentCount of %u which doesn't match the pColorBlendState->attachmentCount of %u. %s", 3117fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis reinterpret_cast<const uint64_t &>(pPipeline->graphicsPipelineCI.renderPass), pPipeline->graphicsPipelineCI.subpass, 3118fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis subpass_desc->colorAttachmentCount, color_blend_state->attachmentCount, 3119fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis validation_error_map[VALIDATION_ERROR_02109]); 3120fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis } 312151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (!dev_data->enabled_features.independentBlend) { 31223d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis if (pPipeline->attachments.size() > 1) { 312326c548826ff0f83d12c769b51e7d6f76d1265c0eChris Forbes VkPipelineColorBlendAttachmentState *pAttachments = &pPipeline->attachments[0]; 3124c7bd67f06427b08ba65cdf2dd529c8234beebdd5Mark Lobodzinski for (size_t i = 1; i < pPipeline->attachments.size(); i++) { 312506811df0256552cd7da9d7297672af377463fc4aMark Mueller // Quoting the spec: "If [the independent blend] feature is not enabled, the VkPipelineColorBlendAttachmentState 312606811df0256552cd7da9d7297672af377463fc4aMark Mueller // settings for all color attachments must be identical." VkPipelineColorBlendAttachmentState contains 312706811df0256552cd7da9d7297672af377463fc4aMark Mueller // only attachment state, so memcmp is best suited for the comparison 312806811df0256552cd7da9d7297672af377463fc4aMark Mueller if (memcmp(static_cast<const void *>(pAttachments), static_cast<const void *>(&pAttachments[i]), 312906811df0256552cd7da9d7297672af377463fc4aMark Mueller sizeof(pAttachments[0]))) { 3130df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= 3131df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 3132df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t &>(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_01532, "DS", 3133df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "Invalid Pipeline CreateInfo: If independent blend feature not " 3134df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "enabled, all elements of pAttachments must be identical. %s", 3135df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski validation_error_map[VALIDATION_ERROR_01532]); 313606811df0256552cd7da9d7297672af377463fc4aMark Mueller break; 3137c7bd67f06427b08ba65cdf2dd529c8234beebdd5Mark Lobodzinski } 31385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 31395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 31405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 314151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (!dev_data->enabled_features.logicOp && (pPipeline->graphicsPipelineCI.pColorBlendState->logicOpEnable != VK_FALSE)) { 314283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= 3143df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 3144df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t &>(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_01533, "DS", 3145f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt "Invalid Pipeline CreateInfo: If logic operations feature not enabled, logicOpEnable must be VK_FALSE. %s", 3146f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt validation_error_map[VALIDATION_ERROR_01533]); 31475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 31485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 31495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3150a61b537fcb6a4f7b92cd217b3964ad7a48109da1Tobin Ehlis // Ensure the subpass index is valid. If not, then validate_and_capture_pipeline_shader_state 31515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // produces nonsense errors that confuse users. Other layers should already 31525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // emit errors for renderpass being invalid. 31539a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto renderPass = GetRenderPassState(dev_data, pPipeline->graphicsPipelineCI.renderPass); 3154fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes if (renderPass && pPipeline->graphicsPipelineCI.subpass >= renderPass->createInfo.subpassCount) { 3155df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 3156df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t &>(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_02122, "DS", 3157cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Invalid Pipeline CreateInfo State: Subpass index %u " 3158cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "is out of range for this renderpass (0..%u). %s", 3159f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt pPipeline->graphicsPipelineCI.subpass, renderPass->createInfo.subpassCount - 1, 3160f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt validation_error_map[VALIDATION_ERROR_02122]); 31615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 31625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3163df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski if (!GetDisables(dev_data)->shader_validation && !validate_and_capture_pipeline_shader_state(dev_data, pPipeline)) { 316483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call = true; 31655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 316652156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes // Each shader's stage must be unique 316752156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes if (pPipeline->duplicate_shaders) { 316852156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes for (uint32_t stage = VK_SHADER_STAGE_VERTEX_BIT; stage & VK_SHADER_STAGE_ALL_GRAPHICS; stage <<= 1) { 316952156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes if (pPipeline->duplicate_shaders & stage) { 3170df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= 3171df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 3172df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t &>(pPipeline->pipeline), __LINE__, DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, 3173df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "DS", "Invalid Pipeline CreateInfo State: Multiple shaders provided for stage %s", 3174df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski string_VkShaderStageFlagBits(VkShaderStageFlagBits(stage))); 317552156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes } 317652156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes } 317752156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes } 31785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // VS is required 31795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!(pPipeline->active_shaders & VK_SHADER_STAGE_VERTEX_BIT)) { 3180df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= 3181df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 3182df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t &>(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_00532, "DS", 3183df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "Invalid Pipeline CreateInfo State: Vertex Shader required. %s", validation_error_map[VALIDATION_ERROR_00532]); 31845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 31855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Either both or neither TC/TE shaders should be defined 3186f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt if ((pPipeline->active_shaders & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) && 3187f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt !(pPipeline->active_shaders & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)) { 3188df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 3189df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t &>(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_00534, "DS", 3190f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt "Invalid Pipeline CreateInfo State: TE and TC shaders must be included or excluded as a pair. %s", 3191f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt validation_error_map[VALIDATION_ERROR_00534]); 3192f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt } 3193f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt if (!(pPipeline->active_shaders & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) && 3194f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt (pPipeline->active_shaders & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)) { 3195df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 3196df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t &>(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_00535, "DS", 3197f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt "Invalid Pipeline CreateInfo State: TE and TC shaders must be included or excluded as a pair. %s", 3198f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt validation_error_map[VALIDATION_ERROR_00535]); 31995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 32005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Compute shaders should be specified independent of Gfx shaders 3201f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt if (pPipeline->active_shaders & VK_SHADER_STAGE_COMPUTE_BIT) { 3202df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 3203df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t &>(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_00533, "DS", 3204f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt "Invalid Pipeline CreateInfo State: Do not specify Compute Shader for Gfx Pipeline. %s", 3205f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt validation_error_map[VALIDATION_ERROR_00533]); 32065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 32075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // VK_PRIMITIVE_TOPOLOGY_PATCH_LIST primitive topology is only valid for tessellation pipelines. 32085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Mismatching primitive topology and tessellation fails graphics pipeline creation. 32095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pPipeline->active_shaders & (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) && 3210ca546210846c65808717f8875deae39bd227c240Tobin Ehlis (!pPipeline->graphicsPipelineCI.pInputAssemblyState || 3211ca546210846c65808717f8875deae39bd227c240Tobin Ehlis pPipeline->graphicsPipelineCI.pInputAssemblyState->topology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST)) { 3212df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 3213df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t &>(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_02099, "DS", 3214cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Invalid Pipeline CreateInfo State: " 3215cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "VK_PRIMITIVE_TOPOLOGY_PATCH_LIST must be set as IA " 3216cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "topology for tessellation pipelines. %s", 3217f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt validation_error_map[VALIDATION_ERROR_02099]); 32185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 3219ca546210846c65808717f8875deae39bd227c240Tobin Ehlis if (pPipeline->graphicsPipelineCI.pInputAssemblyState && 3220ca546210846c65808717f8875deae39bd227c240Tobin Ehlis pPipeline->graphicsPipelineCI.pInputAssemblyState->topology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST) { 32215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (~pPipeline->active_shaders & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) { 3222df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 3223df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t &>(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_02100, "DS", 3224cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Invalid Pipeline CreateInfo State: " 3225cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "VK_PRIMITIVE_TOPOLOGY_PATCH_LIST primitive " 3226cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "topology is only valid for tessellation pipelines. %s", 3227f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt validation_error_map[VALIDATION_ERROR_02100]); 32285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 32295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 3230f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt 3231f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt if (pPipeline->graphicsPipelineCI.pTessellationState && 3232f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt ((pPipeline->graphicsPipelineCI.pTessellationState->patchControlPoints == 0) || 3233f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt (pPipeline->graphicsPipelineCI.pTessellationState->patchControlPoints > 323451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->phys_dev_properties.properties.limits.maxTessellationPatchSize))) { 3235df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 3236df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t &>(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_01426, "DS", 3237cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Invalid Pipeline CreateInfo State: " 3238cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "VK_PRIMITIVE_TOPOLOGY_PATCH_LIST primitive " 3239cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "topology used with patchControlPoints value %u." 3240cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " patchControlPoints should be >0 and <=%u. %s", 3241f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt pPipeline->graphicsPipelineCI.pTessellationState->patchControlPoints, 324251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->phys_dev_properties.properties.limits.maxTessellationPatchSize, 3243f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt validation_error_map[VALIDATION_ERROR_01426]); 3244f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt } 3245f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt 32466b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen // If a rasterization state is provided... 3247a27508babf63d50aea75883a3702979193c23683Mark Young if (pPipeline->graphicsPipelineCI.pRasterizationState) { 32486b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen // Make sure that the line width conforms to the HW. 3249a27508babf63d50aea75883a3702979193c23683Mark Young if (!isDynamic(pPipeline, VK_DYNAMIC_STATE_LINE_WIDTH)) { 3250df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= 3251df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski verifyLineWidth(dev_data, DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, 3252df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, reinterpret_cast<uint64_t const &>(pPipeline->pipeline), 3253df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski pPipeline->graphicsPipelineCI.pRasterizationState->lineWidth); 3254a27508babf63d50aea75883a3702979193c23683Mark Young } 32555dcdd90e54199dfeb29938a3a03d998397c22664Chris Forbes 325658c5552c73679f81f57a64a809f7d4d6d52f4ce3Mark Lobodzinski if ((pPipeline->graphicsPipelineCI.pRasterizationState->depthClampEnable == VK_TRUE) && 325758c5552c73679f81f57a64a809f7d4d6d52f4ce3Mark Lobodzinski (!dev_data->enabled_features.depthClamp)) { 3258df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 3259df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t &>(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_01455, "DS", 326058c5552c73679f81f57a64a809f7d4d6d52f4ce3Mark Lobodzinski "vkCreateGraphicsPipelines(): the depthClamp device feature is disabled: the depthClampEnable " 326158c5552c73679f81f57a64a809f7d4d6d52f4ce3Mark Lobodzinski "member of the VkPipelineRasterizationStateCreateInfo structure must be set to VK_FALSE. %s", 326258c5552c73679f81f57a64a809f7d4d6d52f4ce3Mark Lobodzinski validation_error_map[VALIDATION_ERROR_01455]); 326358c5552c73679f81f57a64a809f7d4d6d52f4ce3Mark Lobodzinski } 326458c5552c73679f81f57a64a809f7d4d6d52f4ce3Mark Lobodzinski 3265434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski if (!isDynamic(pPipeline, VK_DYNAMIC_STATE_DEPTH_BIAS) && 3266434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski (pPipeline->graphicsPipelineCI.pRasterizationState->depthBiasClamp != 0.0) && 3267434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski (!dev_data->enabled_features.depthBiasClamp)) { 3268df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 3269df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t &>(pPipeline->pipeline), __LINE__, DRAWSTATE_INVALID_FEATURE, "DS", 3270434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski "vkCreateGraphicsPipelines(): the depthBiasClamp device feature is disabled: the depthBiasClamp " 3271434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski "member of the VkPipelineRasterizationStateCreateInfo structure must be set to 0.0 unless the " 3272434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski "VK_DYNAMIC_STATE_DEPTH_BIAS dynamic state is enabled"); 3273434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski } 3274434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski 32756b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen // If rasterization is enabled... 32766b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen if (pPipeline->graphicsPipelineCI.pRasterizationState->rasterizerDiscardEnable == VK_FALSE) { 32776b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen auto subpass_desc = renderPass ? &renderPass->createInfo.pSubpasses[pPipeline->graphicsPipelineCI.subpass] : nullptr; 32786b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen 3279148e8028deee2b4b00ccd4a69210897add328265Mark Lobodzinski if ((pPipeline->graphicsPipelineCI.pMultisampleState->alphaToOneEnable == VK_TRUE) && 3280148e8028deee2b4b00ccd4a69210897add328265Mark Lobodzinski (!dev_data->enabled_features.alphaToOne)) { 3281df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 3282df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t &>(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_01464, "DS", 3283148e8028deee2b4b00ccd4a69210897add328265Mark Lobodzinski "vkCreateGraphicsPipelines(): the alphaToOne device feature is disabled: the alphaToOneEnable " 32844c1f7e564e7a3f705ac142b1519c48a83a513b58Mark Lobodzinski "member of the VkPipelineMultisampleStateCreateInfo structure must be set to VK_FALSE. %s", 3285148e8028deee2b4b00ccd4a69210897add328265Mark Lobodzinski validation_error_map[VALIDATION_ERROR_01464]); 3286148e8028deee2b4b00ccd4a69210897add328265Mark Lobodzinski } 3287148e8028deee2b4b00ccd4a69210897add328265Mark Lobodzinski 32886b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen // If subpass uses a depth/stencil attachment, pDepthStencilState must be a pointer to a valid structure 32896b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen if (subpass_desc && subpass_desc->pDepthStencilAttachment && 32906b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen subpass_desc->pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) { 32916b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen if (!pPipeline->graphicsPipelineCI.pDepthStencilState) { 3292df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= 3293df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 3294df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t &>(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_02115, "DS", 3295df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "Invalid Pipeline CreateInfo State: pDepthStencilState is NULL when rasterization is " 3296df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "enabled and subpass uses a depth/stencil attachment. %s", 3297df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski validation_error_map[VALIDATION_ERROR_02115]); 32989580629edfc5154cc9e36974cca12966fbd748b9Mark Lobodzinski 32999580629edfc5154cc9e36974cca12966fbd748b9Mark Lobodzinski } else if ((pPipeline->graphicsPipelineCI.pDepthStencilState->depthBoundsTestEnable == VK_TRUE) && 33009580629edfc5154cc9e36974cca12966fbd748b9Mark Lobodzinski (!dev_data->enabled_features.depthBounds)) { 33019580629edfc5154cc9e36974cca12966fbd748b9Mark Lobodzinski skip_call |= log_msg( 3302df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 3303df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t &>(pPipeline->pipeline), __LINE__, DRAWSTATE_INVALID_FEATURE, "DS", 33049580629edfc5154cc9e36974cca12966fbd748b9Mark Lobodzinski "vkCreateGraphicsPipelines(): the depthBounds device feature is disabled: the depthBoundsTestEnable " 33059580629edfc5154cc9e36974cca12966fbd748b9Mark Lobodzinski "member of the VkPipelineDepthStencilStateCreateInfo structure must be set to VK_FALSE."); 33066b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen } 33075dcdd90e54199dfeb29938a3a03d998397c22664Chris Forbes } 3308326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen 3309326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen // If subpass uses color attachments, pColorBlendState must be valid pointer 3310326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen if (subpass_desc) { 3311326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen uint32_t color_attachment_count = 0; 3312326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen for (uint32_t i = 0; i < subpass_desc->colorAttachmentCount; ++i) { 3313326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen if (subpass_desc->pColorAttachments[i].attachment != VK_ATTACHMENT_UNUSED) { 3314326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen ++color_attachment_count; 3315326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen } 3316326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen } 3317326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen if (color_attachment_count > 0 && pPipeline->graphicsPipelineCI.pColorBlendState == nullptr) { 3318df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= 3319df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 3320df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t &>(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_02116, "DS", 3321df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "Invalid Pipeline CreateInfo State: pColorBlendState is NULL when rasterization is " 3322df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "enabled and subpass uses color attachments. %s", 3323df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski validation_error_map[VALIDATION_ERROR_02116]); 3324326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen } 3325326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen } 33265dcdd90e54199dfeb29938a3a03d998397c22664Chris Forbes } 33275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 33286b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen 332983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis return skip_call; 33305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 33315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 33325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Free the Pipeline nodes 333351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic void deletePipelines(layer_data *dev_data) { 333451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (dev_data->pipelineMap.size() <= 0) return; 333551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis for (auto &pipe_map_pair : dev_data->pipelineMap) { 3336ca546210846c65808717f8875deae39bd227c240Tobin Ehlis delete pipe_map_pair.second; 33375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 333851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->pipelineMap.clear(); 33395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 33405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 33415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Block of code at start here specifically for managing/tracking DSs 33425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 33435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Return Pool node ptr for specified pool or else NULL 33449a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisDESCRIPTOR_POOL_STATE *GetDescriptorPoolState(const layer_data *dev_data, const VkDescriptorPool pool) { 3345bb7ea477706f90eb2a72887f652795bc79f60ddeTobin Ehlis auto pool_it = dev_data->descriptorPoolMap.find(pool); 3346bb7ea477706f90eb2a72887f652795bc79f60ddeTobin Ehlis if (pool_it == dev_data->descriptorPoolMap.end()) { 33475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return NULL; 33485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 3349bb7ea477706f90eb2a72887f652795bc79f60ddeTobin Ehlis return pool_it->second; 33505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 33515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 33525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Validate that given set is valid and that it's not being used by an in-flight CmdBuffer 33535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// func_str is the name of the calling function 3354e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves// Return false if no errors occur 3355e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves// Return true if validation error occurs and callback returns true (to skip upcoming API call down the chain) 33560dcd0f7b37456e2e552d37094ba503c0d089b906Tobin Ehlisstatic bool validateIdleDescriptorSet(const layer_data *dev_data, VkDescriptorSet set, std::string func_str) { 3357cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.idle_descriptor_set) return false; 3358e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool skip_call = false; 33590dcd0f7b37456e2e552d37094ba503c0d089b906Tobin Ehlis auto set_node = dev_data->setMap.find(set); 33600dcd0f7b37456e2e552d37094ba503c0d089b906Tobin Ehlis if (set_node == dev_data->setMap.end()) { 33610dcd0f7b37456e2e552d37094ba503c0d089b906Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, 33625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (uint64_t)(set), __LINE__, DRAWSTATE_DOUBLE_DESTROY, "DS", 3363414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller "Cannot call %s() on descriptor set 0x%" PRIxLEAST64 " that has not been allocated.", func_str.c_str(), 33645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (uint64_t)(set)); 33655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 33661c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis // TODO : This covers various error cases so should pass error enum into this function and use passed in enum here 33675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (set_node->second->in_use.load()) { 33681c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis skip_call |= 33690dcd0f7b37456e2e552d37094ba503c0d089b906Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, 33701c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis (uint64_t)(set), __LINE__, VALIDATION_ERROR_00919, "DS", 33711c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis "Cannot call %s() on descriptor set 0x%" PRIxLEAST64 " that is in use by a command buffer. %s", 33721c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis func_str.c_str(), (uint64_t)(set), validation_error_map[VALIDATION_ERROR_00919]); 33735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 33745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 33755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return skip_call; 33765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 3377f80bf38f4fb3f177b3e1be11b7b1c5edcdbf7d9bChris Forbes 3378e6651096ed8f07840447783c66827cc16d659a49Tobin Ehlis// Remove set from setMap and delete the set 33799dd448578d59cb5ce692e833ba230783b30f3550Tobin Ehlisstatic void freeDescriptorSet(layer_data *dev_data, cvdescriptorset::DescriptorSet *descriptor_set) { 33809dd448578d59cb5ce692e833ba230783b30f3550Tobin Ehlis dev_data->setMap.erase(descriptor_set->GetSet()); 33819dd448578d59cb5ce692e833ba230783b30f3550Tobin Ehlis delete descriptor_set; 33829dd448578d59cb5ce692e833ba230783b30f3550Tobin Ehlis} 33835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Free all DS Pools including their Sets & related sub-structs 33845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// NOTE : Calls to this function should be wrapped in mutex 338551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic void deletePools(layer_data *dev_data) { 338651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (dev_data->descriptorPoolMap.size() <= 0) return; 338751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis for (auto ii = dev_data->descriptorPoolMap.begin(); ii != dev_data->descriptorPoolMap.end(); ++ii) { 3388c5f47f0a54e14c47d402aeabc6498d981ecda9ccTobin Ehlis // Remove this pools' sets from setMap and delete them 3389cb9ce9e05b8e939d3da35c64997c70049877f4feTobin Ehlis for (auto ds : (*ii).second->sets) { 339051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis freeDescriptorSet(dev_data, ds); 33915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 3392f13bee0887f3c3d1d597c82869864be3be836737Tobin Ehlis (*ii).second->sets.clear(); 33935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 339451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->descriptorPoolMap.clear(); 33955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 33965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 339751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic void clearDescriptorPool(layer_data *dev_data, const VkDevice device, const VkDescriptorPool pool, 33985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkDescriptorPoolResetFlags flags) { 33999a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DESCRIPTOR_POOL_STATE *pPool = GetDescriptorPoolState(dev_data, pool); 3400de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis // TODO: validate flags 3401de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis // For every set off of this pool, clear it, remove from setMap, and free cvdescriptorset::DescriptorSet 3402de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis for (auto ds : pPool->sets) { 340351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis freeDescriptorSet(dev_data, ds); 3404de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis } 3405de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis pPool->sets.clear(); 3406de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis // Reset available count for each type and available sets for this pool 3407de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis for (uint32_t i = 0; i < pPool->availableDescriptorTypeCount.size(); ++i) { 3408de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis pPool->availableDescriptorTypeCount[i] = pPool->maxDescriptorTypeCount[i]; 34095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 3410de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis pPool->availableSets = pPool->maxSets; 34115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 34125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 34135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// For given CB object, fetch associated CB Node from map 34149a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisGLOBAL_CB_NODE *GetCBNode(layer_data const *dev_data, const VkCommandBuffer cb) { 341551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis auto it = dev_data->commandBufferMap.find(cb); 341651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (it == dev_data->commandBufferMap.end()) { 34175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return NULL; 34185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 34195121a8dcacb23766ba4455b4eea429f0a3d62099Chris Forbes return it->second; 34205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 34215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Free all CB Nodes 34225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// NOTE : Calls to this function should be wrapped in mutex 342351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic void deleteCommandBuffers(layer_data *dev_data) { 342451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (dev_data->commandBufferMap.empty()) { 34255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return; 34265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 342751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis for (auto ii = dev_data->commandBufferMap.begin(); ii != dev_data->commandBufferMap.end(); ++ii) { 34285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis delete (*ii).second; 34295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 343051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->commandBufferMap.clear(); 34315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 34325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 343329f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis// If a renderpass is active, verify that the given command type is appropriate for current subpass state 343429f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlisbool ValidateCmdSubpassState(const layer_data *dev_data, const GLOBAL_CB_NODE *pCB, const CMD_TYPE cmd_type) { 3435cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!pCB->activeRenderPass) return false; 3436e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool skip_call = false; 3437d0d8e333806eaac08bdc87ddeff886dc2b0f09e7Tobin Ehlis if (pCB->activeSubpassContents == VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS && 3438d0d8e333806eaac08bdc87ddeff886dc2b0f09e7Tobin Ehlis (cmd_type != CMD_EXECUTECOMMANDS && cmd_type != CMD_NEXTSUBPASS && cmd_type != CMD_ENDRENDERPASS)) { 3439df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 3440df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER, "DS", 34415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis "Commands cannot be called in a subpass using secondary command buffers."); 34425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (pCB->activeSubpassContents == VK_SUBPASS_CONTENTS_INLINE && cmd_type == CMD_EXECUTECOMMANDS) { 3443df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 3444df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER, "DS", 34455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis "vkCmdExecuteCommands() cannot be called in a subpass using inline commands."); 34465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 34475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return skip_call; 34485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 34495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3450baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardtbool ValidateCmdQueueFlags(layer_data *dev_data, GLOBAL_CB_NODE *cb_node, const char *caller_name, VkQueueFlags required_flags, 3451baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt UNIQUE_VALIDATION_ERROR_CODE error_code) { 3452baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt auto pool = GetCommandPoolNode(dev_data, cb_node->createInfo.commandPool); 3453baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt if (pool) { 3454baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt VkQueueFlags queue_flags = dev_data->phys_dev_properties.queue_family_properties[pool->queueFamilyIndex].queueFlags; 3455baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt if (!(required_flags & queue_flags)) { 3456baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt string required_flags_string; 3457baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt for (auto flag : {VK_QUEUE_TRANSFER_BIT, VK_QUEUE_GRAPHICS_BIT, VK_QUEUE_COMPUTE_BIT}) { 3458baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt if (flag & required_flags) { 3459baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt if (required_flags_string.size()) { 3460baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt required_flags_string += " or "; 3461baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt } 3462baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt required_flags_string += string_VkQueueFlagBits(flag); 3463baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt } 3464baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt } 3465baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt return log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 3466baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, error_code, "DS", 3467baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt "Cannot call %s on a command buffer allocated from a pool without %s capabilities. %s.", caller_name, 3468baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt required_flags_string.c_str(), validation_error_map[error_code]); 3469baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt } 3470baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt } 34715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 34725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 34735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3474ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinskistatic bool ReportInvalidCommandBuffer(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, const char *call_source) { 3475ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski bool skip = false; 3476ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski for (auto obj : cb_state->broken_bindings) { 3477ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski const char *type_str = object_type_to_string(obj.type); 3478ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski // Descriptor sets are a special case that can be either destroyed or updated to invalidate a CB 3479ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski const char *cause_str = (obj.type == VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT) ? "destroyed or updated" : "destroyed"; 3480ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 3481ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski reinterpret_cast<uint64_t &>(cb_state->commandBuffer), __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER, "DS", 3482ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski "You are adding %s to command buffer 0x%p that is invalid because bound %s 0x%" PRIxLEAST64 " was %s.", 3483ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski call_source, cb_state->commandBuffer, type_str, obj.handle, cause_str); 3484ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } 3485ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski return skip; 3486ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski} 3487ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski 3488623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski// Validate the given command being added to the specified cmd buffer, flagging errors if CB is not in the recording state or if 3489623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski// there's an issue with the Cmd ordering 3490946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinskibool ValidateCmd(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, const CMD_TYPE cmd, const char *caller_name) { 3491946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski bool skip = false; 3492946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (cb_state->state != CB_RECORDING) { 3493946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (cb_state->state == CB_INVALID) { 3494946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ReportInvalidCommandBuffer(dev_data, cb_state, caller_name); 3495ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } else { 3496946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 3497946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski reinterpret_cast<uint64_t &>(cb_state->commandBuffer), __LINE__, DRAWSTATE_NO_BEGIN_COMMAND_BUFFER, 3498946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "DS", "You must call vkBeginCommandBuffer() before this call to %s", caller_name); 3499ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } 35007651c2eb9fe152ba62921ed60454afd882357e2aTobin Ehlis } else { 3501946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ValidateCmdSubpassState(dev_data, cb_state, cmd); 35025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 3503946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski return skip; 35045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 350529f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis 35061ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlisvoid UpdateCmdBufferLastCmd(GLOBAL_CB_NODE *cb_state, const CMD_TYPE cmd) { 350729f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis if (cb_state->state == CB_RECORDING) { 350829f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis cb_state->last_cmd = cmd; 350929f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis } 351029f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis} 35117e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis// For given object struct return a ptr of BASE_NODE type for its wrapping struct 35127e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin EhlisBASE_NODE *GetStateStructPtrFromObject(layer_data *dev_data, VK_OBJECT object_struct) { 35137e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis BASE_NODE *base_ptr = nullptr; 35147e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis switch (object_struct.type) { 3515cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT: { 35169a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetSetNode(dev_data, reinterpret_cast<VkDescriptorSet &>(object_struct.handle)); 3517cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3518cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3519cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT: { 35209a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetSamplerState(dev_data, reinterpret_cast<VkSampler &>(object_struct.handle)); 3521cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3522cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3523cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT: { 35249a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetQueryPoolNode(dev_data, reinterpret_cast<VkQueryPool &>(object_struct.handle)); 3525cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3526cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3527cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT: { 3528cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski base_ptr = getPipelineState(dev_data, reinterpret_cast<VkPipeline &>(object_struct.handle)); 3529cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3530cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3531cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT: { 35329a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetBufferState(dev_data, reinterpret_cast<VkBuffer &>(object_struct.handle)); 3533cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3534cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3535cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT: { 35369a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetBufferViewState(dev_data, reinterpret_cast<VkBufferView &>(object_struct.handle)); 3537cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3538cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3539cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT: { 35409a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetImageState(dev_data, reinterpret_cast<VkImage &>(object_struct.handle)); 3541cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3542cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3543cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT: { 35449a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetImageViewState(dev_data, reinterpret_cast<VkImageView &>(object_struct.handle)); 3545cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3546cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3547cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT: { 35489a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetEventNode(dev_data, reinterpret_cast<VkEvent &>(object_struct.handle)); 3549cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3550cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3551cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT: { 35529a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetDescriptorPoolState(dev_data, reinterpret_cast<VkDescriptorPool &>(object_struct.handle)); 3553cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3554cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3555cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT: { 35569a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetCommandPoolNode(dev_data, reinterpret_cast<VkCommandPool &>(object_struct.handle)); 3557cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3558cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3559cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT: { 35609a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetFramebufferState(dev_data, reinterpret_cast<VkFramebuffer &>(object_struct.handle)); 3561cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3562cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3563cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT: { 35649a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetRenderPassState(dev_data, reinterpret_cast<VkRenderPass &>(object_struct.handle)); 3565cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3566cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3567cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT: { 35689a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetMemObjInfo(dev_data, reinterpret_cast<VkDeviceMemory &>(object_struct.handle)); 3569cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3570cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3571cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 3572cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // TODO : Any other objects to be handled here? 3573cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski assert(0); 3574cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3575bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis } 35767e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis return base_ptr; 35777e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis} 35787e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis 35797e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis// Tie the VK_OBJECT to the cmd buffer which includes: 35807e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis// Add object_binding to cmd buffer 35817e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis// Add cb_binding to object 35827e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlisstatic void addCommandBufferBinding(std::unordered_set<GLOBAL_CB_NODE *> *cb_bindings, VK_OBJECT obj, GLOBAL_CB_NODE *cb_node) { 35837e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis cb_bindings->insert(cb_node); 35847e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis cb_node->object_bindings.insert(obj); 35857e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis} 35867e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis// For a given object, if cb_node is in that objects cb_bindings, remove cb_node 35877e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlisstatic void removeCommandBufferBinding(layer_data *dev_data, VK_OBJECT const *object, GLOBAL_CB_NODE *cb_node) { 35887e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis BASE_NODE *base_obj = GetStateStructPtrFromObject(dev_data, *object); 3589cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (base_obj) base_obj->cb_bindings.erase(cb_node); 3590bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis} 35915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Reset the command buffer state 35925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Maintain the createInfo and set state to CB_NEW, but clear all other state 3593400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlisstatic void resetCB(layer_data *dev_data, const VkCommandBuffer cb) { 3594400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis GLOBAL_CB_NODE *pCB = dev_data->commandBufferMap[cb]; 35955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 3596b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine pCB->in_use.store(0); 3597347d4d3139a1e743ed85bd375c20fd35bbe68d74Chris Forbes pCB->last_cmd = CMD_NONE; 35985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Reset CB state (note that createInfo is not cleared) 35995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->commandBuffer = cb; 36005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis memset(&pCB->beginInfo, 0, sizeof(VkCommandBufferBeginInfo)); 36015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis memset(&pCB->inheritanceInfo, 0, sizeof(VkCommandBufferInheritanceInfo)); 36025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->numCmds = 0; 36035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis memset(pCB->drawCount, 0, NUM_DRAW_TYPES * sizeof(uint64_t)); 36045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->state = CB_NEW; 36055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->submitCount = 0; 36065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->status = 0; 3607b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes pCB->viewportMask = 0; 3608b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes pCB->scissorMask = 0; 360993c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski 361072d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis for (uint32_t i = 0; i < VK_PIPELINE_BIND_POINT_RANGE_SIZE; ++i) { 361172d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis pCB->lastBound[i].reset(); 361272d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis } 361393c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski 36145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis memset(&pCB->activeRenderPassBeginInfo, 0, sizeof(pCB->activeRenderPassBeginInfo)); 3615ee691f5c5fa87aac3750454d2bca2cb582e4e817Chris Forbes pCB->activeRenderPass = nullptr; 36165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->activeSubpassContents = VK_SUBPASS_CONTENTS_INLINE; 36175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->activeSubpass = 0; 3618e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis pCB->broken_bindings.clear(); 36195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->waitedEvents.clear(); 36205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->events.clear(); 3621c7e6bc41aa9c6e5a677b138b9459b252cd3bedf2Mark Lobodzinski pCB->writeEventsBeforeWait.clear(); 36225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->waitedEventsBeforeQueryReset.clear(); 36235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->queryToStateMap.clear(); 36245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->activeQueries.clear(); 36255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->startedQueries.clear(); 3626abfafae4ec5d76e520916b03d196e474e972c949Michael Lentine pCB->imageSubresourceMap.clear(); 36275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->imageLayoutMap.clear(); 36285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->eventToStageMap.clear(); 36295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->drawData.clear(); 36305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->currentDrawData.buffers.clear(); 363158b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis pCB->vertex_buffer_used = false; 36325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->primaryCommandBuffer = VK_NULL_HANDLE; 3633bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis // Make sure any secondaryCommandBuffers are removed from globalInFlight 3634bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis for (auto secondary_cb : pCB->secondaryCommandBuffers) { 3635bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis dev_data->globalInFlightCmdBuffers.erase(secondary_cb); 3636bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis } 36375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->secondaryCommandBuffers.clear(); 36387a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis pCB->updateImages.clear(); 36397a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis pCB->updateBuffers.clear(); 3640400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis clear_cmd_buf_and_mem_references(dev_data, pCB); 3641b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine pCB->eventUpdates.clear(); 3642d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine pCB->queryUpdates.clear(); 364393c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski 3644bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis // Remove object bindings 3645bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis for (auto obj : pCB->object_bindings) { 3646bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis removeCommandBufferBinding(dev_data, &obj, pCB); 3647bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis } 3648a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis pCB->object_bindings.clear(); 364993c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski // Remove this cmdBuffer's reference from each FrameBuffer's CB ref list 365093c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski for (auto framebuffer : pCB->framebuffers) { 36519a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto fb_state = GetFramebufferState(dev_data, framebuffer); 3652cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (fb_state) fb_state->cb_bindings.erase(pCB); 365393c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski } 365493c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski pCB->framebuffers.clear(); 36557003b38da5cc27a063af3c45080f3a35438283eeTobin Ehlis pCB->activeFramebuffer = VK_NULL_HANDLE; 36565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 36575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 36585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 36595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Set PSO-related status bits for CB, including dynamic state set via PSO 36604c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlisstatic void set_cb_pso_status(GLOBAL_CB_NODE *pCB, const PIPELINE_STATE *pPipe) { 36615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Account for any dynamic state not set via this PSO 3662ca546210846c65808717f8875deae39bd227c240Tobin Ehlis if (!pPipe->graphicsPipelineCI.pDynamicState || 3663cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski !pPipe->graphicsPipelineCI.pDynamicState->dynamicStateCount) { // All state is static 36644052946ae557337ff95f3725e879131b1c63f865Tobin Ehlis pCB->status |= CBSTATUS_ALL_STATE_SET; 36655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 36665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // First consider all state on 36675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Then unset any state that's noted as dynamic in PSO 36685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Finally OR that into CB statemask 36694052946ae557337ff95f3725e879131b1c63f865Tobin Ehlis CBStatusFlags psoDynStateMask = CBSTATUS_ALL_STATE_SET; 3670ca546210846c65808717f8875deae39bd227c240Tobin Ehlis for (uint32_t i = 0; i < pPipe->graphicsPipelineCI.pDynamicState->dynamicStateCount; i++) { 3671ca546210846c65808717f8875deae39bd227c240Tobin Ehlis switch (pPipe->graphicsPipelineCI.pDynamicState->pDynamicStates[i]) { 3672cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DYNAMIC_STATE_LINE_WIDTH: 3673cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski psoDynStateMask &= ~CBSTATUS_LINE_WIDTH_SET; 3674cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3675cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DYNAMIC_STATE_DEPTH_BIAS: 3676cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski psoDynStateMask &= ~CBSTATUS_DEPTH_BIAS_SET; 3677cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3678cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DYNAMIC_STATE_BLEND_CONSTANTS: 3679cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski psoDynStateMask &= ~CBSTATUS_BLEND_CONSTANTS_SET; 3680cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3681cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DYNAMIC_STATE_DEPTH_BOUNDS: 3682cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski psoDynStateMask &= ~CBSTATUS_DEPTH_BOUNDS_SET; 3683cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3684cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK: 3685cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski psoDynStateMask &= ~CBSTATUS_STENCIL_READ_MASK_SET; 3686cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3687cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DYNAMIC_STATE_STENCIL_WRITE_MASK: 3688cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski psoDynStateMask &= ~CBSTATUS_STENCIL_WRITE_MASK_SET; 3689cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3690cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DYNAMIC_STATE_STENCIL_REFERENCE: 3691cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski psoDynStateMask &= ~CBSTATUS_STENCIL_REFERENCE_SET; 3692cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3693cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 3694cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // TODO : Flag error here 3695cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 36965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 36975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 36985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->status |= psoDynStateMask; 36995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 37005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 37015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3702623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski// Flags validation error if the associated call is made inside a render pass. The apiName routine should ONLY be called outside a 3703623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski// render pass. 370451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisbool insideRenderPass(const layer_data *dev_data, GLOBAL_CB_NODE *pCB, const char *apiName, UNIQUE_VALIDATION_ERROR_CODE msgCode) { 3705e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool inside = false; 37065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB->activeRenderPass) { 370751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis inside = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 3708ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen (uint64_t)pCB->commandBuffer, __LINE__, msgCode, "DS", 3709ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen "%s: It is invalid to issue this call inside an active render pass (0x%" PRIxLEAST64 "). %s", apiName, 3710ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen (uint64_t)pCB->activeRenderPass->renderPass, validation_error_map[msgCode]); 37115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 37125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return inside; 37135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 37145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 37155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Flags validation error if the associated call is made outside a render pass. The apiName 37165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// routine should ONLY be called inside a render pass. 371751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisbool outsideRenderPass(const layer_data *dev_data, GLOBAL_CB_NODE *pCB, const char *apiName, UNIQUE_VALIDATION_ERROR_CODE msgCode) { 3718e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool outside = false; 37195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (((pCB->createInfo.level == VK_COMMAND_BUFFER_LEVEL_PRIMARY) && (!pCB->activeRenderPass)) || 37205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis ((pCB->createInfo.level == VK_COMMAND_BUFFER_LEVEL_SECONDARY) && (!pCB->activeRenderPass) && 37215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis !(pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT))) { 372251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis outside = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 3723ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen (uint64_t)pCB->commandBuffer, __LINE__, msgCode, "DS", 3724ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen "%s: This call must be issued inside an active render pass. %s", apiName, validation_error_map[msgCode]); 37255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 37265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return outside; 37275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 37285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3729f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbesstatic void init_core_validation(instance_layer_data *instance_data, const VkAllocationCallbacks *pAllocator) { 3730b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis layer_debug_actions(instance_data->report_data, instance_data->logging_callback, pAllocator, "lunarg_core_validation"); 37315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 37325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3733747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbesstatic void checkInstanceRegisterExtensions(const VkInstanceCreateInfo *pCreateInfo, instance_layer_data *instance_data) { 3734747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) { 3735747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SURFACE_EXTENSION_NAME)) 3736747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->surfaceExtensionEnabled = true; 3737747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_DISPLAY_EXTENSION_NAME)) 3738747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->displayExtensionEnabled = true; 3739747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_ANDROID_KHR 3740747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_ANDROID_SURFACE_EXTENSION_NAME)) 3741747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->androidSurfaceExtensionEnabled = true; 3742747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif 3743747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_MIR_KHR 3744747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_MIR_SURFACE_EXTENSION_NAME)) 3745747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->mirSurfaceExtensionEnabled = true; 3746747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif 3747747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_WAYLAND_KHR 3748747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME)) 3749747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->waylandSurfaceExtensionEnabled = true; 3750747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif 3751747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_WIN32_KHR 3752747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_WIN32_SURFACE_EXTENSION_NAME)) 3753747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->win32SurfaceExtensionEnabled = true; 3754747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif 3755747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_XCB_KHR 3756747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_XCB_SURFACE_EXTENSION_NAME)) 3757747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->xcbSurfaceExtensionEnabled = true; 3758747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif 3759747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_XLIB_KHR 3760747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_XLIB_SURFACE_EXTENSION_NAME)) 3761747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->xlibSurfaceExtensionEnabled = true; 3762747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif 3763747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes } 3764747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 3765747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 37667a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis// For the given ValidationCheck enum, set all relevant instance disabled flags to true 37677a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlisvoid SetDisabledFlags(instance_layer_data *instance_data, VkValidationFlagsEXT *val_flags_struct) { 37687a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis for (uint32_t i = 0; i < val_flags_struct->disabledValidationCheckCount; ++i) { 37697a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis switch (val_flags_struct->pDisabledValidationChecks[i]) { 37707a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis case VK_VALIDATION_CHECK_ALL_EXT: 37717a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis // Set all disabled flags to true 37727a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis instance_data->disabled.SetAll(true); 37737a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis break; 37747a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis default: 37757a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis break; 37767a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis } 37777a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis } 37787a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis} 37797a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis 3780bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, 3781bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkInstance *pInstance) { 37825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO); 37835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 37845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(chain_info->u.pLayerInfo); 37855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr; 37865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance"); 3787cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED; 37885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 37895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Advance the link info for the next element on the chain 37905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext; 37915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 37925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance); 3793cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (result != VK_SUCCESS) return result; 37945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 379556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(*pInstance), instance_layer_data_map); 379656a5ba3e60a723781945959ffc10e2e215350de5Chia-I Wu instance_data->instance = *pInstance; 37979172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes layer_init_instance_dispatch_table(*pInstance, &instance_data->dispatch_table, fpGetInstanceProcAddr); 37989172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes instance_data->report_data = debug_report_create_instance( 37999172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes &instance_data->dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount, pCreateInfo->ppEnabledExtensionNames); 3800747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes checkInstanceRegisterExtensions(pCreateInfo, instance_data); 3801b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis init_core_validation(instance_data, pAllocator); 3802825ac70f99460ccb9494d34f93d8ee7ec303e5deMark Lobodzinski 38035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis ValidateLayerOrdering(*pCreateInfo); 38047a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis // Parse any pNext chains 38057a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis if (pCreateInfo->pNext) { 38067a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis GENERIC_HEADER *struct_header = (GENERIC_HEADER *)pCreateInfo->pNext; 38077a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis while (struct_header) { 38087a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis // Check for VkValidationFlagsExt 38097a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis if (VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT == struct_header->sType) { 38107a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis SetDisabledFlags(instance_data, (VkValidationFlagsEXT *)struct_header); 38117a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis } 38127a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis struct_header = (GENERIC_HEADER *)struct_header->pNext; 38137a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis } 38147a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis } 38155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 38165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 38175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 38185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 381925002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// Hook DestroyInstance to remove tableInstanceMap entry 382089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) { 38215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODOSC : Shouldn't need any customization here 38225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dispatch_key key = get_dispatch_key(instance); 38235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TBD: Need any locking this early, in case this function is called at the 38245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // same time by more than one thread? 382556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(key, instance_layer_data_map); 38269172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes instance_data->dispatch_table.DestroyInstance(instance, pAllocator); 38275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3828b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 38295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Clean up logging callback, if any 38309172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes while (instance_data->logging_callback.size() > 0) { 38319172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes VkDebugReportCallbackEXT callback = instance_data->logging_callback.back(); 38329172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes layer_destroy_msg_callback(instance_data->report_data, callback, pAllocator); 38339172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes instance_data->logging_callback.pop_back(); 38345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 38355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 38369172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes layer_debug_report_destroy_instance(instance_data->report_data); 38375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis layer_data_map.erase(key); 38385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 38395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3840373469f006399d6b5204ee05db3b56beb168b36fMark Youngstatic void checkDeviceRegisterExtensions(const VkDeviceCreateInfo *pCreateInfo, VkDevice device) { 38415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t i; 3842bee1d36c54af112766d4e8552ad302f39290683aMark Lobodzinski // TBD: Need any locking, in case this function is called at the same time by more than one thread? 384356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 38445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->device_extensions.wsi_enabled = false; 3845c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young dev_data->device_extensions.wsi_display_swapchain_enabled = false; 3846bee1d36c54af112766d4e8552ad302f39290683aMark Lobodzinski dev_data->device_extensions.nv_glsl_shader_enabled = false; 38476246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski dev_data->device_extensions.khr_descriptor_update_template_enabled = false; 384881b2d76c449bb91569776e2b8e68130f509d53bcChris Forbes dev_data->device_extensions.khr_shader_draw_parameters_enabled = false; 38490e2296e24065d02615ee87561bbb80af414a1ddfMike Schuchardt dev_data->device_extensions.khr_maintenance1_enabled = false; 38502664122d97c3f0a98b3e5d12833bbb20196ca837Mark Lobodzinski dev_data->device_extensions.nv_geometry_shader_passthrough_enabled = false; 38515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 38525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (i = 0; i < pCreateInfo->enabledExtensionCount; i++) { 3853bee1d36c54af112766d4e8552ad302f39290683aMark Lobodzinski if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SWAPCHAIN_EXTENSION_NAME) == 0) { 38545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->device_extensions.wsi_enabled = true; 3855bee1d36c54af112766d4e8552ad302f39290683aMark Lobodzinski } 3856bee1d36c54af112766d4e8552ad302f39290683aMark Lobodzinski if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_DISPLAY_SWAPCHAIN_EXTENSION_NAME) == 0) { 3857c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young dev_data->device_extensions.wsi_display_swapchain_enabled = true; 3858bee1d36c54af112766d4e8552ad302f39290683aMark Lobodzinski } 3859bee1d36c54af112766d4e8552ad302f39290683aMark Lobodzinski if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_NV_GLSL_SHADER_EXTENSION_NAME) == 0) { 3860bee1d36c54af112766d4e8552ad302f39290683aMark Lobodzinski dev_data->device_extensions.nv_glsl_shader_enabled = true; 3861bee1d36c54af112766d4e8552ad302f39290683aMark Lobodzinski } 38626246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME) == 0) { 38636246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski dev_data->device_extensions.khr_descriptor_update_template_enabled = true; 38646246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski } 386581b2d76c449bb91569776e2b8e68130f509d53bcChris Forbes if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME) == 0) { 386681b2d76c449bb91569776e2b8e68130f509d53bcChris Forbes dev_data->device_extensions.khr_shader_draw_parameters_enabled = true; 386781b2d76c449bb91569776e2b8e68130f509d53bcChris Forbes } 38680e2296e24065d02615ee87561bbb80af414a1ddfMike Schuchardt if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_MAINTENANCE1_EXTENSION_NAME) == 0) { 38690e2296e24065d02615ee87561bbb80af414a1ddfMike Schuchardt dev_data->device_extensions.khr_maintenance1_enabled = true; 38700e2296e24065d02615ee87561bbb80af414a1ddfMike Schuchardt } 38712664122d97c3f0a98b3e5d12833bbb20196ca837Mark Lobodzinski if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_NV_GEOMETRY_SHADER_PASSTHROUGH_EXTENSION_NAME) == 0) { 38722664122d97c3f0a98b3e5d12833bbb20196ca837Mark Lobodzinski dev_data->device_extensions.nv_geometry_shader_passthrough_enabled = true; 38732664122d97c3f0a98b3e5d12833bbb20196ca837Mark Lobodzinski } 38745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 38755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 38765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3877838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski// Verify that queue family has been properly requested 3878ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblenstatic bool ValidateRequestedQueueFamilyProperties(instance_layer_data *instance_data, VkPhysicalDevice gpu, 3879ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen const VkDeviceCreateInfo *create_info) { 3880838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski bool skip_call = false; 38819a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto physical_device_state = GetPhysicalDeviceState(instance_data, gpu); 3882838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski // First check is app has actually requested queueFamilyProperties 38834b293996aa6a9bd92ef1f0175eca4b0e8a9fd9fcChris Forbes if (!physical_device_state) { 3884bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski skip_call |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 3885bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_MUST_QUERY_COUNT, "DL", 3886838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski "Invalid call to vkCreateDevice() w/o first calling vkEnumeratePhysicalDevices()."); 38874b293996aa6a9bd92ef1f0175eca4b0e8a9fd9fcChris Forbes } else if (QUERY_DETAILS != physical_device_state->vkGetPhysicalDeviceQueueFamilyPropertiesState) { 3888838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski // TODO: This is not called out as an invalid use in the spec so make more informative recommendation. 38894b293996aa6a9bd92ef1f0175eca4b0e8a9fd9fcChris Forbes skip_call |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, 3890838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_INVALID_QUEUE_CREATE_REQUEST, 3891838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski "DL", "Call to vkCreateDevice() w/o first calling vkGetPhysicalDeviceQueueFamilyProperties()."); 3892838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski } else { 3893838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski // Check that the requested queue properties are valid 3894838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski for (uint32_t i = 0; i < create_info->queueCreateInfoCount; i++) { 3895838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski uint32_t requestedIndex = create_info->pQueueCreateInfos[i].queueFamilyIndex; 38967d8b6ab1b68c397da50bad43deb1fba389ebace7Chris Forbes if (requestedIndex >= physical_device_state->queue_family_properties.size()) { 3897838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski skip_call |= log_msg( 38984b293996aa6a9bd92ef1f0175eca4b0e8a9fd9fcChris Forbes instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, 3899838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski __LINE__, DEVLIMITS_INVALID_QUEUE_CREATE_REQUEST, "DL", 3900838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski "Invalid queue create request in vkCreateDevice(). Invalid queueFamilyIndex %u requested.", requestedIndex); 3901838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski } else if (create_info->pQueueCreateInfos[i].queueCount > 39027d8b6ab1b68c397da50bad43deb1fba389ebace7Chris Forbes physical_device_state->queue_family_properties[requestedIndex].queueCount) { 3903cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski skip_call |= log_msg( 3904cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, 3905cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, DEVLIMITS_INVALID_QUEUE_CREATE_REQUEST, "DL", 3906cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Invalid queue create request in vkCreateDevice(). QueueFamilyIndex %u only has %u queues, but " 3907cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "requested queueCount is %u.", 3908cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski requestedIndex, physical_device_state->queue_family_properties[requestedIndex].queueCount, 3909cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski create_info->pQueueCreateInfos[i].queueCount); 3910838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski } 3911838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski } 3912838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski } 3913838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski return skip_call; 3914838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski} 3915838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski 3916f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski// Verify that features have been queried and that they are available 3917bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic bool ValidateRequestedFeatures(instance_layer_data *dev_data, VkPhysicalDevice phys, 3918bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkPhysicalDeviceFeatures *requested_features) { 3919f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski bool skip_call = false; 3920f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski 39219a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto phys_device_state = GetPhysicalDeviceState(dev_data, phys); 39223bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes const VkBool32 *actual = reinterpret_cast<VkBool32 *>(&phys_device_state->features); 3923825ac70f99460ccb9494d34f93d8ee7ec303e5deMark Lobodzinski const VkBool32 *requested = reinterpret_cast<const VkBool32 *>(requested_features); 3924f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski // TODO : This is a nice, compact way to loop through struct, but a bad way to report issues 3925f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski // Need to provide the struct member name with the issue. To do that seems like we'll 3926f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski // have to loop through each struct member which should be done w/ codegen to keep in synch. 3927f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski uint32_t errors = 0; 3928f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski uint32_t total_bools = sizeof(VkPhysicalDeviceFeatures) / sizeof(VkBool32); 3929f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski for (uint32_t i = 0; i < total_bools; i++) { 3930f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski if (requested[i] > actual[i]) { 3931f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski // TODO: Add index to struct member name helper to be able to include a feature name 3932cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski skip_call |= 3933cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, 3934cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, DEVLIMITS_INVALID_FEATURE_REQUESTED, "DL", 3935cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "While calling vkCreateDevice(), requesting feature #%u in VkPhysicalDeviceFeatures struct, " 3936cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "which is not available on this device.", 3937cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski i); 3938f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski errors++; 3939f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski } 3940f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski } 39413bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes if (errors && (UNCALLED == phys_device_state->vkGetPhysicalDeviceFeaturesState)) { 3942f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski // If user didn't request features, notify them that they should 3943f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski // TODO: Verify this against the spec. I believe this is an invalid use of the API and should return an error 3944bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 3945bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski 0, __LINE__, DEVLIMITS_INVALID_FEATURE_REQUESTED, "DL", 3946bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "You requested features that are unavailable on this device. You should first query feature " 3947bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "availability by calling vkGetPhysicalDeviceFeatures()."); 3948f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski } 3949f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski return skip_call; 3950f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski} 3951f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski 395289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo, 395389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) { 395456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(gpu), instance_layer_data_map); 3955f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski bool skip_call = false; 3956f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski 3957f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski // Check that any requested features are available 3958f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski if (pCreateInfo->pEnabledFeatures) { 395956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis skip_call |= ValidateRequestedFeatures(instance_data, gpu, pCreateInfo->pEnabledFeatures); 3960f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski } 396156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis skip_call |= ValidateRequestedQueueFamilyProperties(instance_data, gpu, pCreateInfo); 3962f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski 39631d659b4113b77a95325df10d602a03f1e7abf8b7Mark Mueller if (skip_call) { 39641d659b4113b77a95325df10d602a03f1e7abf8b7Mark Mueller return VK_ERROR_VALIDATION_FAILED_EXT; 39651d659b4113b77a95325df10d602a03f1e7abf8b7Mark Mueller } 39661d659b4113b77a95325df10d602a03f1e7abf8b7Mark Mueller 39675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO); 39685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 39695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(chain_info->u.pLayerInfo); 39705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr; 39715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr; 397256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_data->instance, "vkCreateDevice"); 39735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (fpCreateDevice == NULL) { 39745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return VK_ERROR_INITIALIZATION_FAILED; 39755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 39765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 39775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Advance the link info for the next element on the chain 39785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext; 39795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 39805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice); 39815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (result != VK_SUCCESS) { 39825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 39835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 39845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3985b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 398656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *device_data = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map); 39875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 398856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis device_data->instance_data = instance_data; 39895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Setup device dispatch table 399056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_init_device_dispatch_table(*pDevice, &device_data->dispatch_table, fpGetDeviceProcAddr); 399156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis device_data->device = *pDevice; 3992ec85232c4d8d9ddf7d2ae57cb8203c5ab52c1106Mark Lobodzinski // Save PhysicalDevice handle 399356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis device_data->physical_device = gpu; 39945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 399556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis device_data->report_data = layer_debug_report_create_device(instance_data->report_data, *pDevice); 3996373469f006399d6b5204ee05db3b56beb168b36fMark Young checkDeviceRegisterExtensions(pCreateInfo, *pDevice); 39975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Get physical device limits for this device 399856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_data->dispatch_table.GetPhysicalDeviceProperties(gpu, &(device_data->phys_dev_properties.properties)); 39995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t count; 400056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_data->dispatch_table.GetPhysicalDeviceQueueFamilyProperties(gpu, &count, nullptr); 400156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis device_data->phys_dev_properties.queue_family_properties.resize(count); 400256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_data->dispatch_table.GetPhysicalDeviceQueueFamilyProperties( 400356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis gpu, &count, &device_data->phys_dev_properties.queue_family_properties[0]); 40045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODO: device limits should make sure these are compatible 40055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCreateInfo->pEnabledFeatures) { 400656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis device_data->enabled_features = *pCreateInfo->pEnabledFeatures; 40075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 400856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis memset(&device_data->enabled_features, 0, sizeof(VkPhysicalDeviceFeatures)); 40095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 4010e47dbc3f3340fa177d877a67b2adb76a570027e5Mark Lobodzinski // Store physical device properties and physical device mem limits into device layer_data structs 401156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_data->dispatch_table.GetPhysicalDeviceMemoryProperties(gpu, &device_data->phys_dev_mem_props); 401256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_data->dispatch_table.GetPhysicalDeviceProperties(gpu, &device_data->phys_dev_props); 4013b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 40145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 40155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis ValidateLayerOrdering(*pCreateInfo); 40165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 40175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 40185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 40195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 40205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// prototype 402189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) { 40225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODOSC : Shouldn't need any customization here 40233ec39aeb6d6f08fb1ee45f64f72543a710754c62Tobin Ehlis bool skip = false; 40245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dispatch_key key = get_dispatch_key(device); 402556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(key, layer_data_map); 40265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Free all the memory 4027b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 40285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis deletePipelines(dev_data); 4029fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes dev_data->renderPassMap.clear(); 40305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis deleteCommandBuffers(dev_data); 4031f13bee0887f3c3d1d597c82869864be3be836737Tobin Ehlis // This will also delete all sets in the pool & remove them from setMap 40325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis deletePools(dev_data); 4033f13bee0887f3c3d1d597c82869864be3be836737Tobin Ehlis // All sets should be removed 4034f13bee0887f3c3d1d597c82869864be3be836737Tobin Ehlis assert(dev_data->setMap.empty()); 4035a1e5173c89eb7f03e0434ad45ccd1471e722fa71Tobin Ehlis for (auto del_layout : dev_data->descriptorSetLayoutMap) { 4036a1e5173c89eb7f03e0434ad45ccd1471e722fa71Tobin Ehlis delete del_layout.second; 4037a1e5173c89eb7f03e0434ad45ccd1471e722fa71Tobin Ehlis } 4038fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis dev_data->descriptorSetLayoutMap.clear(); 40395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->imageViewMap.clear(); 40405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->imageMap.clear(); 40415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->imageSubresourceMap.clear(); 40425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->imageLayoutMap.clear(); 40435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->bufferViewMap.clear(); 40445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->bufferMap.clear(); 40451344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis // Queues persist until device is destroyed 40461344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis dev_data->queueMap.clear(); 40475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Report any memory leaks 40485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis layer_debug_report_destroy_device(device); 4049b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 40505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 40515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#if DISPATCH_MAP_DEBUG 4052414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller fprintf(stderr, "Device: 0x%p, key: 0x%p\n", device, key); 40535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#endif 40543ec39aeb6d6f08fb1ee45f64f72543a710754c62Tobin Ehlis if (!skip) { 40554a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyDevice(device, pAllocator); 40563ec39aeb6d6f08fb1ee45f64f72543a710754c62Tobin Ehlis layer_data_map.erase(key); 40575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 40585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 40595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 40605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}}; 40615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4062208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis// For given stage mask, if Geometry shader stage is on w/o GS being enabled, report geo_error_id 4063208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis// and if Tessellation Control or Evaluation shader stages are on w/o TS being enabled, report tess_error_id 4064208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlisstatic bool ValidateStageMaskGsTsEnables(layer_data *dev_data, VkPipelineStageFlags stageMask, const char *caller, 4065208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis UNIQUE_VALIDATION_ERROR_CODE geo_error_id, UNIQUE_VALIDATION_ERROR_CODE tess_error_id) { 4066208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis bool skip = false; 4067208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis if (!dev_data->enabled_features.geometryShader && (stageMask & VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT)) { 4068208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 4069cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski geo_error_id, "DL", 4070cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s call includes a stageMask with VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT bit set when " 4071cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "device does not have geometryShader feature enabled. %s", 4072208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis caller, validation_error_map[geo_error_id]); 4073208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis } 4074208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis if (!dev_data->enabled_features.tessellationShader && 4075208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis (stageMask & (VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT | VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT))) { 4076208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 4077cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski tess_error_id, "DL", 4078cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s call includes a stageMask with VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT " 4079cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "and/or VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT bit(s) set when device " 4080cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "does not have tessellationShader feature enabled. %s", 4081208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis caller, validation_error_map[tess_error_id]); 4082208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis } 4083208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis return skip; 4084208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis} 4085208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis 4086ad97d033b614e6265aaa8c8f0d21a044982d4de7Jeremy Hayes// Loop through bound objects and increment their in_use counts. 4087ad97d033b614e6265aaa8c8f0d21a044982d4de7Jeremy Hayesstatic void IncrementBoundObjects(layer_data *dev_data, GLOBAL_CB_NODE const *cb_node) { 4088a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis for (auto obj : cb_node->object_bindings) { 4089a317e7593a0fe227635fc8241908471acb36c952Chris Forbes auto base_obj = GetStateStructPtrFromObject(dev_data, obj); 4090ad97d033b614e6265aaa8c8f0d21a044982d4de7Jeremy Hayes if (base_obj) { 409151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour base_obj->in_use.fetch_add(1); 4092162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis } 4093a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis } 4094a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis} 40955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Track which resources are in-flight by atomically incrementing their "in_use" count 409651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourstatic void incrementResources(layer_data *dev_data, GLOBAL_CB_NODE *cb_node) { 409751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour cb_node->submitCount++; 40989a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis cb_node->in_use.fetch_add(1); 40999a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis dev_data->globalInFlightCmdBuffers.insert(cb_node->commandBuffer); 4100a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes 4101a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis // First Increment for all "generic" objects bound to cmd buffer, followed by special-case objects below 4102ad97d033b614e6265aaa8c8f0d21a044982d4de7Jeremy Hayes IncrementBoundObjects(dev_data, cb_node); 4103a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis // TODO : We should be able to remove the NULL look-up checks from the code below as long as 4104a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis // all the corresponding cases are verified to cause CB_INVALID state and the CB_INVALID state 4105a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis // should then be flagged prior to calling this function 41069a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis for (auto drawDataElement : cb_node->drawData) { 41075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto buffer : drawDataElement.buffers) { 41089a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto buffer_state = GetBufferState(dev_data, buffer); 410951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (buffer_state) { 41105cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis buffer_state->in_use.fetch_add(1); 41115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 41125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 41135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 41149a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis for (auto event : cb_node->writeEventsBeforeWait) { 41159a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto event_state = GetEventNode(dev_data, event); 4116cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (event_state) event_state->write_in_use++; 4117c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine } 41185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 41195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4120b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis// Note: This function assumes that the global lock is held by the calling thread. 4121b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis// For the given queue, verify the queue state up to the given seq number. 4122b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis// Currently the only check is to make sure that if there are events to be waited on prior to 4123b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis// a QueryReset, make sure that all such events have been signalled. 412436c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlisstatic bool VerifyQueueStateToSeq(layer_data *dev_data, QUEUE_STATE *queue, uint64_t seq) { 4125b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis bool skip = false; 4126b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis auto queue_seq = queue->seq; 412792b1701c552e96e96fdbbb77e4b106a9526f3b8cTobin Ehlis std::unordered_map<VkQueue, uint64_t> other_queue_seqs; 412892b1701c552e96e96fdbbb77e4b106a9526f3b8cTobin Ehlis auto sub_it = queue->submissions.begin(); 4129b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis while (queue_seq < seq) { 413092b1701c552e96e96fdbbb77e4b106a9526f3b8cTobin Ehlis for (auto &wait : sub_it->waitSemaphores) { 413192b1701c552e96e96fdbbb77e4b106a9526f3b8cTobin Ehlis auto &last_seq = other_queue_seqs[wait.queue]; 413292b1701c552e96e96fdbbb77e4b106a9526f3b8cTobin Ehlis last_seq = std::max(last_seq, wait.seq); 413392b1701c552e96e96fdbbb77e4b106a9526f3b8cTobin Ehlis } 413492b1701c552e96e96fdbbb77e4b106a9526f3b8cTobin Ehlis for (auto cb : sub_it->cbs) { 41359a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, cb); 4136b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis if (cb_node) { 4137b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis for (auto queryEventsPair : cb_node->waitedEventsBeforeQueryReset) { 4138b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis for (auto event : queryEventsPair.second) { 413992b1701c552e96e96fdbbb77e4b106a9526f3b8cTobin Ehlis if (dev_data->eventMap[event].needsSignaled) { 414092b1701c552e96e96fdbbb77e4b106a9526f3b8cTobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 4141b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, 0, DRAWSTATE_INVALID_QUERY, "DS", 4142b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis "Cannot get query results on queryPool 0x%" PRIx64 4143b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis " with index %d which was guarded by unsignaled event 0x%" PRIx64 ".", 4144b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis (uint64_t)(queryEventsPair.first.pool), queryEventsPair.first.index, (uint64_t)(event)); 4145b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis } 4146b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis } 4147b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine } 4148b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine } 4149b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine } 415092b1701c552e96e96fdbbb77e4b106a9526f3b8cTobin Ehlis sub_it++; 4151b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis queue_seq++; 4152b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine } 415392b1701c552e96e96fdbbb77e4b106a9526f3b8cTobin Ehlis for (auto qs : other_queue_seqs) { 41549a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis skip |= VerifyQueueStateToSeq(dev_data, GetQueueState(dev_data, qs.first), qs.second); 415592b1701c552e96e96fdbbb77e4b106a9526f3b8cTobin Ehlis } 4156b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis return skip; 4157b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis} 4158b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis 4159b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis// When the given fence is retired, verify outstanding queue operations through the point of the fence 4160b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlisstatic bool VerifyQueueStateToFence(layer_data *dev_data, VkFence fence) { 41619a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto fence_state = GetFenceNode(dev_data, fence); 4162b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis if (VK_NULL_HANDLE != fence_state->signaler.first) { 41639a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis return VerifyQueueStateToSeq(dev_data, GetQueueState(dev_data, fence_state->signaler.first), fence_state->signaler.second); 4164b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis } 4165b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis return false; 4166b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine} 41677d33205c3aa4aba751a2c07f956634aac616f916Chris Forbes 41687d33205c3aa4aba751a2c07f956634aac616f916Chris Forbes// TODO: nuke this completely. 4169b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine// Decrement cmd_buffer in_use and if it goes to 0 remove cmd_buffer from globalInFlightCmdBuffers 4170b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentinestatic inline void removeInFlightCmdBuffer(layer_data *dev_data, VkCommandBuffer cmd_buffer) { 4171b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine // Pull it off of global list initially, but if we find it in any other queue list, add it back in 41729a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, cmd_buffer); 4173b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine pCB->in_use.fetch_sub(1); 4174b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine if (!pCB->in_use.load()) { 4175b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine dev_data->globalInFlightCmdBuffers.erase(cmd_buffer); 4176b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine } 4177b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine} 4178b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine 4179a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis// Decrement in-use count for objects bound to command buffer 41802f8cbf3b166e175174877a59929902e005953d6dTobin Ehlisstatic void DecrementBoundResources(layer_data *dev_data, GLOBAL_CB_NODE const *cb_node) { 418100e8ce2e6c1c191758f7b7c15eeaf350e5b4a3b6Tobin Ehlis BASE_NODE *base_obj = nullptr; 4182a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis for (auto obj : cb_node->object_bindings) { 41837e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis base_obj = GetStateStructPtrFromObject(dev_data, obj); 418400e8ce2e6c1c191758f7b7c15eeaf350e5b4a3b6Tobin Ehlis if (base_obj) { 418500e8ce2e6c1c191758f7b7c15eeaf350e5b4a3b6Tobin Ehlis base_obj->in_use.fetch_sub(1); 418600e8ce2e6c1c191758f7b7c15eeaf350e5b4a3b6Tobin Ehlis } 4187a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis } 4188a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis} 4189da8f07baf262972eb3e719fa07b073c180dff157Chris Forbes 419036c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlisstatic void RetireWorkOnQueue(layer_data *dev_data, QUEUE_STATE *pQueue, uint64_t seq) { 41919867daedbf52debc77d6568162ee21e071699b80Chris Forbes std::unordered_map<VkQueue, uint64_t> otherQueueSeqs; 41929867daedbf52debc77d6568162ee21e071699b80Chris Forbes 41939867daedbf52debc77d6568162ee21e071699b80Chris Forbes // Roll this queue forward, one submission at a time. 41949867daedbf52debc77d6568162ee21e071699b80Chris Forbes while (pQueue->seq < seq) { 4195bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto &submission = pQueue->submissions.front(); 41969867daedbf52debc77d6568162ee21e071699b80Chris Forbes 4197bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski for (auto &wait : submission.waitSemaphores) { 41989a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pSemaphore = GetSemaphoreNode(dev_data, wait.semaphore); 4199c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski if (pSemaphore) { 4200c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski pSemaphore->in_use.fetch_sub(1); 4201c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski } 4202bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto &lastSeq = otherQueueSeqs[wait.queue]; 42039867daedbf52debc77d6568162ee21e071699b80Chris Forbes lastSeq = std::max(lastSeq, wait.seq); 4204da8f07baf262972eb3e719fa07b073c180dff157Chris Forbes } 4205cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes 4206bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski for (auto &semaphore : submission.signalSemaphores) { 42079a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pSemaphore = GetSemaphoreNode(dev_data, semaphore); 4208c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski if (pSemaphore) { 4209c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski pSemaphore->in_use.fetch_sub(1); 4210c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski } 42119867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 4212cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes 42139867daedbf52debc77d6568162ee21e071699b80Chris Forbes for (auto cb : submission.cbs) { 42149a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, cb); 4215c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski if (!cb_node) { 4216c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski continue; 4217c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski } 4218a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis // First perform decrement on general case bound objects 42199a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis DecrementBoundResources(dev_data, cb_node); 42209a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis for (auto drawDataElement : cb_node->drawData) { 42219867daedbf52debc77d6568162ee21e071699b80Chris Forbes for (auto buffer : drawDataElement.buffers) { 42229a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto buffer_state = GetBufferState(dev_data, buffer); 42235cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis if (buffer_state) { 42245cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis buffer_state->in_use.fetch_sub(1); 42259867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 42269867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 4227da8f07baf262972eb3e719fa07b073c180dff157Chris Forbes } 42289a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis for (auto event : cb_node->writeEventsBeforeWait) { 42299867daedbf52debc77d6568162ee21e071699b80Chris Forbes auto eventNode = dev_data->eventMap.find(event); 42309867daedbf52debc77d6568162ee21e071699b80Chris Forbes if (eventNode != dev_data->eventMap.end()) { 42319867daedbf52debc77d6568162ee21e071699b80Chris Forbes eventNode->second.write_in_use--; 42329867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 42339867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 42349a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis for (auto queryStatePair : cb_node->queryToStateMap) { 42359867daedbf52debc77d6568162ee21e071699b80Chris Forbes dev_data->queryToStateMap[queryStatePair.first] = queryStatePair.second; 42369867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 42379a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis for (auto eventStagePair : cb_node->eventToStageMap) { 42389867daedbf52debc77d6568162ee21e071699b80Chris Forbes dev_data->eventMap[eventStagePair.first].stageMask = eventStagePair.second; 4239da8f07baf262972eb3e719fa07b073c180dff157Chris Forbes } 42400a32ed7bdf03e7bda914e03c0bfa6ebf400cdf5bMichael Lentine 42419867daedbf52debc77d6568162ee21e071699b80Chris Forbes removeInFlightCmdBuffer(dev_data, cb); 42420a32ed7bdf03e7bda914e03c0bfa6ebf400cdf5bMichael Lentine } 42439867daedbf52debc77d6568162ee21e071699b80Chris Forbes 42449a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pFence = GetFenceNode(dev_data, submission.fence); 42459867daedbf52debc77d6568162ee21e071699b80Chris Forbes if (pFence) { 42469867daedbf52debc77d6568162ee21e071699b80Chris Forbes pFence->state = FENCE_RETIRED; 42470a32ed7bdf03e7bda914e03c0bfa6ebf400cdf5bMichael Lentine } 42489867daedbf52debc77d6568162ee21e071699b80Chris Forbes 42499867daedbf52debc77d6568162ee21e071699b80Chris Forbes pQueue->submissions.pop_front(); 42509867daedbf52debc77d6568162ee21e071699b80Chris Forbes pQueue->seq++; 4251b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine } 42529867daedbf52debc77d6568162ee21e071699b80Chris Forbes 42539867daedbf52debc77d6568162ee21e071699b80Chris Forbes // Roll other queues forward to the highest seq we saw a wait for 42549867daedbf52debc77d6568162ee21e071699b80Chris Forbes for (auto qs : otherQueueSeqs) { 42559a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis RetireWorkOnQueue(dev_data, GetQueueState(dev_data, qs.first), qs.second); 4256d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 42579867daedbf52debc77d6568162ee21e071699b80Chris Forbes} 4258651d92815dfff917308137bb67aacccc4f60df86Chris Forbes 4259651d92815dfff917308137bb67aacccc4f60df86Chris Forbes// Submit a fence to a queue, delimiting previous fences and previous untracked 4260651d92815dfff917308137bb67aacccc4f60df86Chris Forbes// work by it. 426136c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlisstatic void SubmitFence(QUEUE_STATE *pQueue, FENCE_NODE *pFence, uint64_t submitCount) { 4262cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes pFence->state = FENCE_INFLIGHT; 42639867daedbf52debc77d6568162ee21e071699b80Chris Forbes pFence->signaler.first = pQueue->queue; 42649867daedbf52debc77d6568162ee21e071699b80Chris Forbes pFence->signaler.second = pQueue->seq + pQueue->submissions.size() + submitCount; 4265b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine} 4266b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine 426751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourstatic bool validateCommandBufferSimultaneousUse(layer_data *dev_data, GLOBAL_CB_NODE *pCB, int current_submit_count) { 42685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool skip_call = false; 426951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if ((dev_data->globalInFlightCmdBuffers.count(pCB->commandBuffer) || current_submit_count > 1) && 42705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis !(pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT)) { 4271226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 4272f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen 0, __LINE__, VALIDATION_ERROR_00133, "DS", 4273f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen "Command Buffer 0x%p is already in use and is not marked for simultaneous use. %s", pCB->commandBuffer, 4274f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen validation_error_map[VALIDATION_ERROR_00133]); 42755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 42765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return skip_call; 42775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 42785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4279946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinskistatic bool validateCommandBufferState(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, const char *call_source, 4280440bdd357701497c3442e3515f12ac1cfffc180aTony Barbour int current_submit_count) { 4281c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis bool skip = false; 4282cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.command_buffer_state) return skip; 42830a59acde4b40fde3bbfea5811d2abf2c85ca62f4Tobin Ehlis // Validate ONE_TIME_SUBMIT_BIT CB is not being submitted more than once 4284946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if ((cb_state->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT) && 4285946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski (cb_state->submitCount + current_submit_count > 1)) { 4286c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, 4287c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis __LINE__, DRAWSTATE_COMMAND_BUFFER_SINGLE_SUBMIT_VIOLATION, "DS", 4288226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "Commandbuffer 0x%p was begun w/ VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT " 4289c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis "set, but has been submitted 0x%" PRIxLEAST64 " times.", 4290946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->commandBuffer, cb_state->submitCount + current_submit_count); 42910a59acde4b40fde3bbfea5811d2abf2c85ca62f4Tobin Ehlis } 42925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Validate that cmd buffers have been updated 4293946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (CB_RECORDED != cb_state->state) { 4294946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (CB_INVALID == cb_state->state) { 4295946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ReportInvalidCommandBuffer(dev_data, cb_state, call_source); 4296cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else { // Flag error for using CB w/o vkEndCommandBuffer() called 4297c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 4298946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski (uint64_t)(cb_state->commandBuffer), __LINE__, DRAWSTATE_NO_END_COMMAND_BUFFER, "DS", 4299946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "You must call vkEndCommandBuffer() on command buffer 0x%p before this call to %s!", 4300946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->commandBuffer, call_source); 43015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 43025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 4303c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis return skip; 43045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 43055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 430651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourstatic bool validateResources(layer_data *dev_data, GLOBAL_CB_NODE *cb_node) { 430751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour bool skip_call = false; 430851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 430951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour // TODO : We should be able to remove the NULL look-up checks from the code below as long as 431051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour // all the corresponding cases are verified to cause CB_INVALID state and the CB_INVALID state 431151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour // should then be flagged prior to calling this function 431251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour for (auto drawDataElement : cb_node->drawData) { 431351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour for (auto buffer : drawDataElement.buffers) { 431451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour auto buffer_state = GetBufferState(dev_data, buffer); 431551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (!buffer_state) { 431651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, 431751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour (uint64_t)(buffer), __LINE__, DRAWSTATE_INVALID_BUFFER, "DS", 431851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour "Cannot submit cmd buffer using deleted buffer 0x%" PRIx64 ".", (uint64_t)(buffer)); 431951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 432051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 432151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 432251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour return skip_call; 432351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour} 432451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 4325f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski// Check that the queue family index of 'queue' matches one of the entries in pQueueFamilyIndices 4326f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinskibool ValidImageBufferQueue(layer_data *dev_data, GLOBAL_CB_NODE *cb_node, const VK_OBJECT *object, VkQueue queue, uint32_t count, 4327f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski const uint32_t *indices) { 4328f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski bool found = false; 4329f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski bool skip = false; 4330f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski auto queue_state = GetQueueState(dev_data, queue); 4331f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski if (queue_state) { 4332f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski for (uint32_t i = 0; i < count; i++) { 4333f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski if (indices[i] == queue_state->queueFamilyIndex) { 4334f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski found = true; 4335f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski break; 4336f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski } 4337f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski } 4338f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski 4339f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski if (!found) { 4340f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski auto type_string = (object->type == VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT ? "image" : "buffer"); 4341f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski skip = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, object->type, object->handle, __LINE__, 4342f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski DRAWSTATE_INVALID_QUEUE_FAMILY, "DS", 4343f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski "vkQueueSubmit: Command buffer 0x%" PRIxLEAST64 " contains %s 0x%" PRIxLEAST64 4344f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski " which was not created allowing concurrent access to this queue family %d.", 4345f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski reinterpret_cast<uint64_t>(cb_node->commandBuffer), type_string, object->handle, 4346f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski queue_state->queueFamilyIndex); 4347f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski } 4348f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski } 4349f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski return skip; 4350f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski} 4351f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski 43527bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski// Validate that queueFamilyIndices of primary command buffers match this queue 43537bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski// Secondary command buffers were previously validated in vkCmdExecuteCommands(). 43547bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinskistatic bool validateQueueFamilyIndices(layer_data *dev_data, GLOBAL_CB_NODE *pCB, VkQueue queue) { 43557bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski bool skip_call = false; 43569a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pPool = GetCommandPoolNode(dev_data, pCB->createInfo.commandPool); 43579a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto queue_state = GetQueueState(dev_data, queue); 43587bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski 4359f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski if (pPool && queue_state) { 4360f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski if (pPool->queueFamilyIndex != queue_state->queueFamilyIndex) { 4361f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski skip_call |= 4362f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 4363f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski reinterpret_cast<uint64_t>(pCB->commandBuffer), __LINE__, VALIDATION_ERROR_00139, "DS", 4364f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski "vkQueueSubmit: Primary command buffer 0x%p created in queue family %d is being submitted on queue " 4365f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski "0x%p from queue family %d. %s", 4366f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski pCB->commandBuffer, pPool->queueFamilyIndex, queue, queue_state->queueFamilyIndex, 4367f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski validation_error_map[VALIDATION_ERROR_00139]); 4368f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski } 4369f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski 4370f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski // Ensure that any bound images or buffers created with SHARING_MODE_CONCURRENT have access to the current queue family 4371f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski for (auto object : pCB->object_bindings) { 4372f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski if (object.type == VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT) { 4373f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski auto image_state = GetImageState(dev_data, reinterpret_cast<VkImage &>(object.handle)); 4374f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski if (image_state && image_state->createInfo.sharingMode == VK_SHARING_MODE_CONCURRENT) { 4375f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski skip_call |= ValidImageBufferQueue(dev_data, pCB, &object, queue, image_state->createInfo.queueFamilyIndexCount, 4376f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski image_state->createInfo.pQueueFamilyIndices); 4377f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski } 4378f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski } else if (object.type == VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT) { 4379f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski auto buffer_state = GetBufferState(dev_data, reinterpret_cast<VkBuffer &>(object.handle)); 4380f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski if (buffer_state && buffer_state->createInfo.sharingMode == VK_SHARING_MODE_CONCURRENT) { 4381f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski skip_call |= 4382f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski ValidImageBufferQueue(dev_data, pCB, &object, queue, buffer_state->createInfo.queueFamilyIndexCount, 4383f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski buffer_state->createInfo.pQueueFamilyIndices); 4384f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski } 4385f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski } 4386f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski } 43877bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski } 43887bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski 43897bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski return skip_call; 43907bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski} 43917bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski 439251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourstatic bool validatePrimaryCommandBufferState(layer_data *dev_data, GLOBAL_CB_NODE *pCB, int current_submit_count) { 43935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Track in-use for resources off of primary and any secondary CBs 439483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 4395a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes 4396a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes // If USAGE_SIMULTANEOUS_USE_BIT not set then CB cannot already be executing 4397a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes // on device 439851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour skip_call |= validateCommandBufferSimultaneousUse(dev_data, pCB, current_submit_count); 4399a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes 440051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour skip_call |= validateResources(dev_data, pCB); 4401a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes 44025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!pCB->secondaryCommandBuffers.empty()) { 44035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto secondaryCmdBuffer : pCB->secondaryCommandBuffers) { 44049a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pSubCB = GetCBNode(dev_data, secondaryCmdBuffer); 440551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour skip_call |= validateResources(dev_data, pSubCB); 44064c665b29a9d2906a378417546c7fc6436731d07fTobin Ehlis if ((pSubCB->primaryCommandBuffer != pCB->commandBuffer) && 44074c665b29a9d2906a378417546c7fc6436731d07fTobin Ehlis !(pSubCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT)) { 4408f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen log_msg( 4409f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, 4410f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen __LINE__, VALIDATION_ERROR_00135, "DS", 4411f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen "Commandbuffer 0x%p was submitted with secondary buffer 0x%p but that buffer has subsequently been bound to " 4412f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen "primary cmd buffer 0x%p and it does not have VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT set. %s", 4413f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen pCB->commandBuffer, secondaryCmdBuffer, pSubCB->primaryCommandBuffer, 4414f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen validation_error_map[VALIDATION_ERROR_00135]); 44155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 44165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 44175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 4418a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes 441951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour skip_call |= validateCommandBufferState(dev_data, pCB, "vkQueueSubmit()", current_submit_count); 4420a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes 442183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis return skip_call; 44225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 44235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4424bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic bool ValidateFenceForSubmit(layer_data *dev_data, FENCE_NODE *pFence) { 442583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 442681c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes 4427651d92815dfff917308137bb67aacccc4f60df86Chris Forbes if (pFence) { 4428cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes if (pFence->state == FENCE_INFLIGHT) { 4429f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen // TODO: opportunities for VALIDATION_ERROR_00127, VALIDATION_ERROR_01647, VALIDATION_ERROR_01953 443083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, 443183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis (uint64_t)(pFence->fence), __LINE__, DRAWSTATE_INVALID_FENCE, "DS", 443283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis "Fence 0x%" PRIx64 " is already in use by another submission.", (uint64_t)(pFence->fence)); 4433a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis } 443481c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes 4435cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes else if (pFence->state == FENCE_RETIRED) { 4436f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen // TODO: opportunities for VALIDATION_ERROR_00126, VALIDATION_ERROR_01646, VALIDATION_ERROR_01953 443783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= 443883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, 443983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis reinterpret_cast<uint64_t &>(pFence->fence), __LINE__, MEMTRACK_INVALID_FENCE_STATE, "MEM", 444083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis "Fence 0x%" PRIxLEAST64 " submitted in SIGNALED state. Fences must be reset before being submitted", 444183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis reinterpret_cast<uint64_t &>(pFence->fence)); 4442a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis } 44435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 444481c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes 444583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis return skip_call; 444681c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes} 444781c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes 444851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourstatic void PostCallRecordQueueSubmit(layer_data *dev_data, VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, 444951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour VkFence fence) { 44509a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pQueue = GetQueueState(dev_data, queue); 44519a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pFence = GetFenceNode(dev_data, fence); 4452d7d60cccc862fee2d0b3ad410c5fdcc40ddc83aeChris Forbes 4453651d92815dfff917308137bb67aacccc4f60df86Chris Forbes // Mark the fence in-use. 4454651d92815dfff917308137bb67aacccc4f60df86Chris Forbes if (pFence) { 44559867daedbf52debc77d6568162ee21e071699b80Chris Forbes SubmitFence(pQueue, pFence, std::max(1u, submitCount)); 4456651d92815dfff917308137bb67aacccc4f60df86Chris Forbes } 4457651d92815dfff917308137bb67aacccc4f60df86Chris Forbes 445851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour // Now process each individual submit 44595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) { 446051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour std::vector<VkCommandBuffer> cbs; 44615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkSubmitInfo *submit = &pSubmits[submit_idx]; 44629867daedbf52debc77d6568162ee21e071699b80Chris Forbes vector<SEMAPHORE_WAIT> semaphore_waits; 44639867daedbf52debc77d6568162ee21e071699b80Chris Forbes vector<VkSemaphore> semaphore_signals; 44645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < submit->waitSemaphoreCount; ++i) { 446551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour VkSemaphore semaphore = submit->pWaitSemaphores[i]; 446651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour auto pSemaphore = GetSemaphoreNode(dev_data, semaphore); 446751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (pSemaphore) { 446851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (pSemaphore->signaler.first != VK_NULL_HANDLE) { 446951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour semaphore_waits.push_back({semaphore, pSemaphore->signaler.first, pSemaphore->signaler.second}); 447051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pSemaphore->in_use.fetch_add(1); 447151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 447251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pSemaphore->signaler.first = VK_NULL_HANDLE; 447351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pSemaphore->signaled = false; 447451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 447551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 447651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour for (uint32_t i = 0; i < submit->signalSemaphoreCount; ++i) { 447751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour VkSemaphore semaphore = submit->pSignalSemaphores[i]; 447851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour auto pSemaphore = GetSemaphoreNode(dev_data, semaphore); 447951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (pSemaphore) { 448051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pSemaphore->signaler.first = queue; 448151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pSemaphore->signaler.second = pQueue->seq + pQueue->submissions.size() + 1; 448251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pSemaphore->signaled = true; 448351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pSemaphore->in_use.fetch_add(1); 448451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour semaphore_signals.push_back(semaphore); 448551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 448651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 448751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour for (uint32_t i = 0; i < submit->commandBufferCount; i++) { 448851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour auto cb_node = GetCBNode(dev_data, submit->pCommandBuffers[i]); 448951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (cb_node) { 449051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour cbs.push_back(submit->pCommandBuffers[i]); 449151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour for (auto secondaryCmdBuffer : cb_node->secondaryCommandBuffers) { 449251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour cbs.push_back(secondaryCmdBuffer); 449351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 449451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour UpdateCmdBufImageLayouts(dev_data, cb_node); 449551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour incrementResources(dev_data, cb_node); 449651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (!cb_node->secondaryCommandBuffers.empty()) { 449751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour for (auto secondaryCmdBuffer : cb_node->secondaryCommandBuffers) { 449851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour GLOBAL_CB_NODE *pSubCB = GetCBNode(dev_data, secondaryCmdBuffer); 449951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour incrementResources(dev_data, pSubCB); 450051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 450151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 450251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 450351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 450451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pQueue->submissions.emplace_back(cbs, semaphore_waits, semaphore_signals, 450551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour submit_idx == submitCount - 1 ? fence : VK_NULL_HANDLE); 450651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 450751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 450851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (pFence && !submitCount) { 450951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour // If no submissions, but just dropping a fence on the end of the queue, 451051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour // record an empty submission with just the fence, so we can determine 451151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour // its completion. 451251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pQueue->submissions.emplace_back(std::vector<VkCommandBuffer>(), std::vector<SEMAPHORE_WAIT>(), std::vector<VkSemaphore>(), 451351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour fence); 451451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 451551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour} 451651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 451751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourstatic bool PreCallValidateQueueSubmit(layer_data *dev_data, VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, 451851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour VkFence fence) { 451951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour auto pFence = GetFenceNode(dev_data, fence); 452051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour bool skip_call = ValidateFenceForSubmit(dev_data, pFence); 452151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (skip_call) { 452251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour return true; 452351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 452451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 452551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour unordered_set<VkSemaphore> signaled_semaphores; 452651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour unordered_set<VkSemaphore> unsignaled_semaphores; 452751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour vector<VkCommandBuffer> current_cmds; 452851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour unordered_map<ImageSubresourcePair, IMAGE_LAYOUT_NODE> localImageLayoutMap = dev_data->imageLayoutMap; 452951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour // Now verify each individual submit 453051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) { 453151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour const VkSubmitInfo *submit = &pSubmits[submit_idx]; 453251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour for (uint32_t i = 0; i < submit->waitSemaphoreCount; ++i) { 4533208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis skip_call |= ValidateStageMaskGsTsEnables(dev_data, submit->pWaitDstStageMask[i], "vkQueueSubmit()", 4534208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis VALIDATION_ERROR_00142, VALIDATION_ERROR_00143); 453501a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes VkSemaphore semaphore = submit->pWaitSemaphores[i]; 45369a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pSemaphore = GetSemaphoreNode(dev_data, semaphore); 453701a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes if (pSemaphore) { 453851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (unsignaled_semaphores.count(semaphore) || 4539440bdd357701497c3442e3515f12ac1cfffc180aTony Barbour (!(signaled_semaphores.count(semaphore)) && !(pSemaphore->signaled))) { 454083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= 45411344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT, 45421344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis reinterpret_cast<const uint64_t &>(semaphore), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS", 4543226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "Queue 0x%p is waiting on semaphore 0x%" PRIx64 " that has no way to be signaled.", queue, 4544226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis reinterpret_cast<const uint64_t &>(semaphore)); 454551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } else { 454651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour signaled_semaphores.erase(semaphore); 454751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour unsignaled_semaphores.insert(semaphore); 45481344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis } 45495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 45505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 45515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < submit->signalSemaphoreCount; ++i) { 455201a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes VkSemaphore semaphore = submit->pSignalSemaphores[i]; 45539a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pSemaphore = GetSemaphoreNode(dev_data, semaphore); 455401a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes if (pSemaphore) { 4555440bdd357701497c3442e3515f12ac1cfffc180aTony Barbour if (signaled_semaphores.count(semaphore) || (!(unsignaled_semaphores.count(semaphore)) && pSemaphore->signaled)) { 455683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= 45571344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT, 45581344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis reinterpret_cast<const uint64_t &>(semaphore), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS", 4559226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "Queue 0x%p is signaling semaphore 0x%" PRIx64 4560414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller " that has already been signaled but not waited on by queue 0x%" PRIx64 ".", 4561226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis queue, reinterpret_cast<const uint64_t &>(semaphore), 45629867daedbf52debc77d6568162ee21e071699b80Chris Forbes reinterpret_cast<uint64_t &>(pSemaphore->signaler.first)); 45631344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis } else { 456451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour unsignaled_semaphores.erase(semaphore); 456551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour signaled_semaphores.insert(semaphore); 45661344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis } 45670a32ed7bdf03e7bda914e03c0bfa6ebf400cdf5bMichael Lentine } 45685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 45695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < submit->commandBufferCount; i++) { 45709a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, submit->pCommandBuffers[i]); 4571d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis if (cb_node) { 4572b34ce3b0eda520db569665ae02ec5f6f0e8b6fd1Mark Lobodzinski skip_call |= ValidateCmdBufImageLayouts(dev_data, cb_node, localImageLayoutMap); 457351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour current_cmds.push_back(submit->pCommandBuffers[i]); 457451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour skip_call |= validatePrimaryCommandBufferState( 457551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour dev_data, cb_node, (int)std::count(current_cmds.begin(), current_cmds.end(), submit->pCommandBuffers[i])); 4576d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis skip_call |= validateQueueFamilyIndices(dev_data, cb_node, queue); 457751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 4578ea371fa7c8c57edb4d1436e4570cf54f3fc0463fTobin Ehlis // Potential early exit here as bad object state may crash in delayed function calls 457951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (skip_call) { 458051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour return true; 458151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 458251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 45831344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis // Call submit-time functions to validate/update state 4584d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis for (auto &function : cb_node->validate_functions) { 458583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= function(); 45861344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis } 4587d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis for (auto &function : cb_node->eventUpdates) { 458883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= function(queue); 45891344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis } 4590d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis for (auto &function : cb_node->queryUpdates) { 459183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= function(queue); 4592d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 45931344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis } 45945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 45959867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 459651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour return skip_call; 459751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour} 45989867daedbf52debc77d6568162ee21e071699b80Chris Forbes 459951920949f887ce8d3666c73c28ff19a5d8325a37Tony BarbourVKAPI_ATTR VkResult VKAPI_CALL QueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence) { 460051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map); 460151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour std::unique_lock<std::mutex> lock(global_lock); 460251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 460351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour bool skip = PreCallValidateQueueSubmit(dev_data, queue, submitCount, pSubmits, fence); 4604b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 46055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4606440bdd357701497c3442e3515f12ac1cfffc180aTony Barbour if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 460751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 460851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour VkResult result = dev_data->dispatch_table.QueueSubmit(queue, submitCount, pSubmits, fence); 460951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 461051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour lock.lock(); 461151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour PostCallRecordQueueSubmit(dev_data, queue, submitCount, pSubmits, fence); 461251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour lock.unlock(); 46135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 46145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 46155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4616f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultzstatic bool PreCallValidateAllocateMemory(layer_data *dev_data) { 4617f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz bool skip = false; 4618f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz if (dev_data->memObjMap.size() >= dev_data->phys_dev_properties.properties.limits.maxMemoryAllocationCount) { 4619f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 4620f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz reinterpret_cast<const uint64_t &>(dev_data->device), __LINE__, VALIDATION_ERROR_00611, "MEM", 4621f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz "Number of currently valid memory objects is not less than the maximum allowed (%u). %s", 4622f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz dev_data->phys_dev_properties.properties.limits.maxMemoryAllocationCount, 4623f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz validation_error_map[VALIDATION_ERROR_00611]); 4624f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz } 4625f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz return skip; 4626f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz} 4627f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz 4628f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultzstatic void PostCallRecordAllocateMemory(layer_data *dev_data, const VkMemoryAllocateInfo *pAllocateInfo, VkDeviceMemory *pMemory) { 4629f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz add_mem_obj_info(dev_data, dev_data->device, *pMemory, pAllocateInfo); 4630f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz return; 4631f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz} 4632f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz 463389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL AllocateMemory(VkDevice device, const VkMemoryAllocateInfo *pAllocateInfo, 463489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkDeviceMemory *pMemory) { 4635f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 463656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 4637f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz std::unique_lock<std::mutex> lock(global_lock); 4638f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz bool skip = PreCallValidateAllocateMemory(dev_data); 4639f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz if (!skip) { 4640f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz lock.unlock(); 4641f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz result = dev_data->dispatch_table.AllocateMemory(device, pAllocateInfo, pAllocator, pMemory); 4642f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz lock.lock(); 4643f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz if (VK_SUCCESS == result) { 4644f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz PostCallRecordAllocateMemory(dev_data, pAllocateInfo, pMemory); 4645f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz } 4646e12739a56d02ca2fb5f0273862668e7475a21a6cMark Lobodzinski } 46475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 46485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 46495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4650177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis// For given obj node, if it is use, flag a validation error and return callback result, else return false 4651177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlisbool ValidateObjectNotInUse(const layer_data *dev_data, BASE_NODE *obj_node, VK_OBJECT obj_struct, 4652177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis UNIQUE_VALIDATION_ERROR_CODE error_code) { 4653cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.object_in_use) return false; 4654177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis bool skip = false; 4655177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis if (obj_node->in_use.load()) { 4656177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, obj_struct.type, obj_struct.handle, __LINE__, 4657177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis error_code, "DS", "Cannot delete %s 0x%" PRIx64 " that is currently in use by a command buffer. %s", 4658177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis object_type_to_string(obj_struct.type), obj_struct.handle, validation_error_map[error_code]); 4659177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis } 4660177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis return skip; 4661177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis} 46625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4663177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlisstatic bool PreCallValidateFreeMemory(layer_data *dev_data, VkDeviceMemory mem, DEVICE_MEM_INFO **mem_info, VK_OBJECT *obj_struct) { 46649a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *mem_info = GetMemObjInfo(dev_data, mem); 466594165f5005d1fa37801d49067fe7751789b89d27Tobin Ehlis *obj_struct = {reinterpret_cast<uint64_t &>(mem), VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT}; 4666cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.free_memory) return false; 4667177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis bool skip = false; 4668177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis if (*mem_info) { 4669177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis skip |= ValidateObjectNotInUse(dev_data, *mem_info, *obj_struct, VALIDATION_ERROR_00620); 4670177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis } 4671177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis return skip; 4672177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis} 46735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4674177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlisstatic void PostCallRecordFreeMemory(layer_data *dev_data, VkDeviceMemory mem, DEVICE_MEM_INFO *mem_info, VK_OBJECT obj_struct) { 4675177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis // Clear mem binding for any bound objects 467647705d01140c9f1492885e6efc5fa262e7e1c6a0Tobin Ehlis for (auto obj : mem_info->obj_bindings) { 467747705d01140c9f1492885e6efc5fa262e7e1c6a0Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, obj.type, obj.handle, __LINE__, MEMTRACK_FREED_MEM_REF, 467847705d01140c9f1492885e6efc5fa262e7e1c6a0Tobin Ehlis "MEM", "VK Object 0x%" PRIxLEAST64 " still has a reference to mem obj 0x%" PRIxLEAST64, obj.handle, 467947705d01140c9f1492885e6efc5fa262e7e1c6a0Tobin Ehlis (uint64_t)mem_info->mem); 468047705d01140c9f1492885e6efc5fa262e7e1c6a0Tobin Ehlis switch (obj.type) { 4681cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT: { 46829a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_state = GetImageState(dev_data, reinterpret_cast<VkImage &>(obj.handle)); 4683cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski assert(image_state); // Any destroyed images should already be removed from bindings 4684cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski image_state->binding.mem = MEMORY_UNBOUND; 4685cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 4686cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 4687cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT: { 46889a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto buffer_state = GetBufferState(dev_data, reinterpret_cast<VkBuffer &>(obj.handle)); 4689cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski assert(buffer_state); // Any destroyed buffers should already be removed from bindings 4690cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski buffer_state->binding.mem = MEMORY_UNBOUND; 4691cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 4692cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 4693cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 4694cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Should only have buffer or image objects bound to memory 4695cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski assert(0); 4696177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis } 4697177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis } 4698177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis // Any bound cmd buffers are now invalid 469939c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis invalidateCommandBuffers(dev_data, mem_info->cb_bindings, obj_struct); 4700177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis dev_data->memObjMap.erase(mem); 4701177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis} 4702177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis 4703177063aac84fac6f4e650c2629a08b48be643f96Tobin EhlisVKAPI_ATTR void VKAPI_CALL FreeMemory(VkDevice device, VkDeviceMemory mem, const VkAllocationCallbacks *pAllocator) { 470456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 4705177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis DEVICE_MEM_INFO *mem_info = nullptr; 4706177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis VK_OBJECT obj_struct; 4707b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 4708177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis bool skip = PreCallValidateFreeMemory(dev_data, mem, &mem_info, &obj_struct); 4709177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis if (!skip) { 4710177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis lock.unlock(); 4711177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis dev_data->dispatch_table.FreeMemory(device, mem, pAllocator); 4712177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis lock.lock(); 4713405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (mem != VK_NULL_HANDLE) { 4714405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordFreeMemory(dev_data, mem, mem_info, obj_struct); 4715405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 471674243a735fe102b370237ddf80d3e6f7ec5246dbMark Mueller } 47175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 47185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4719f57fc64ac43691ad98e1713886b345465573070aTobin Ehlis// Validate that given Map memory range is valid. This means that the memory should not already be mapped, 4720f57fc64ac43691ad98e1713886b345465573070aTobin Ehlis// and that the size of the map range should be: 4721f57fc64ac43691ad98e1713886b345465573070aTobin Ehlis// 1. Not zero 4722f57fc64ac43691ad98e1713886b345465573070aTobin Ehlis// 2. Within the size of the memory allocation 472351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool ValidateMapMemRange(layer_data *dev_data, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size) { 472483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 47255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 47265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (size == 0) { 472751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 472883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis (uint64_t)mem, __LINE__, MEMTRACK_INVALID_MAP, "MEM", 472983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis "VkMapMemory: Attempting to map memory range of size zero"); 47305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 47315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 473251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis auto mem_element = dev_data->memObjMap.find(mem); 473351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (mem_element != dev_data->memObjMap.end()) { 473457fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis auto mem_info = mem_element->second.get(); 47355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // It is an application error to call VkMapMemory on an object that is already mapped 4736de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis if (mem_info->mem_range.size != 0) { 473751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 473883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis (uint64_t)mem, __LINE__, MEMTRACK_INVALID_MAP, "MEM", 473983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis "VkMapMemory: Attempting to map memory on an already-mapped object 0x%" PRIxLEAST64, (uint64_t)mem); 47405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 47415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 47425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Validate that offset + size is within object's allocationSize 47435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (size == VK_WHOLE_SIZE) { 4744de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis if (offset >= mem_info->alloc_info.allocationSize) { 474551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call = 474651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 474751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis (uint64_t)mem, __LINE__, MEMTRACK_INVALID_MAP, "MEM", 474851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis "Mapping Memory from 0x%" PRIx64 " to 0x%" PRIx64 474951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis " with size of VK_WHOLE_SIZE oversteps total array size 0x%" PRIx64, 475051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis offset, mem_info->alloc_info.allocationSize, mem_info->alloc_info.allocationSize); 47515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 47525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 4753de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis if ((offset + size) > mem_info->alloc_info.allocationSize) { 4754f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen skip_call = log_msg( 475551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 4756f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen (uint64_t)mem, __LINE__, VALIDATION_ERROR_00628, "MEM", 4757f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen "Mapping Memory from 0x%" PRIx64 " to 0x%" PRIx64 " oversteps total array size 0x%" PRIx64 ". %s", offset, 4758f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen size + offset, mem_info->alloc_info.allocationSize, validation_error_map[VALIDATION_ERROR_00628]); 47595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 47605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 47615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 476283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis return skip_call; 47635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 47645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 476551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic void storeMemRanges(layer_data *dev_data, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size) { 47669a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto mem_info = GetMemObjInfo(dev_data, mem); 476757fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis if (mem_info) { 4768de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis mem_info->mem_range.offset = offset; 4769de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis mem_info->mem_range.size = size; 47705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 47715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 47725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 477351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool deleteMemRanges(layer_data *dev_data, VkDeviceMemory mem) { 477483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 47759a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto mem_info = GetMemObjInfo(dev_data, mem); 477657fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis if (mem_info) { 4777de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis if (!mem_info->mem_range.size) { 47785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Valid Usage: memory must currently be mapped 477951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis skip_call = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 4780f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen (uint64_t)mem, __LINE__, VALIDATION_ERROR_00649, "MEM", 4781f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen "Unmapping Memory without memory being mapped: mem obj 0x%" PRIxLEAST64 ". %s", (uint64_t)mem, 4782f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen validation_error_map[VALIDATION_ERROR_00649]); 47835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 4784de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis mem_info->mem_range.size = 0; 47855f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski if (mem_info->shadow_copy) { 47865f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski free(mem_info->shadow_copy_base); 47875f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski mem_info->shadow_copy_base = 0; 47885f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski mem_info->shadow_copy = 0; 47895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 47905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 479183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis return skip_call; 47925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 47935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 47945f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski// Guard value for pad data 47955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic char NoncoherentMemoryFillValue = 0xb; 47965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 47975f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinskistatic void initializeAndTrackMemory(layer_data *dev_data, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size, 47985f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski void **ppData) { 47999a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto mem_info = GetMemObjInfo(dev_data, mem); 480057fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis if (mem_info) { 4801de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis mem_info->p_driver_data = *ppData; 4802de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis uint32_t index = mem_info->alloc_info.memoryTypeIndex; 4803b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis if (dev_data->phys_dev_mem_props.memoryTypes[index].propertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) { 48045f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski mem_info->shadow_copy = 0; 48055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 48065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (size == VK_WHOLE_SIZE) { 48075f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski size = mem_info->alloc_info.allocationSize - offset; 48085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 48095f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski mem_info->shadow_pad_size = dev_data->phys_dev_properties.properties.limits.minMemoryMapAlignment; 48105f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski assert(vk_safe_modulo(mem_info->shadow_pad_size, 48115f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski dev_data->phys_dev_properties.properties.limits.minMemoryMapAlignment) == 0); 48125f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski // Ensure start of mapped region reflects hardware alignment constraints 48135f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski uint64_t map_alignment = dev_data->phys_dev_properties.properties.limits.minMemoryMapAlignment; 48145f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski 48155f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski // From spec: (ppData - offset) must be aligned to at least limits::minMemoryMapAlignment. 48165f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski uint64_t start_offset = offset % map_alignment; 48175f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski // Data passed to driver will be wrapped by a guardband of data to detect over- or under-writes. 4818bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski mem_info->shadow_copy_base = 4819bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski malloc(static_cast<size_t>(2 * mem_info->shadow_pad_size + size + map_alignment + start_offset)); 48205f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski 48215f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski mem_info->shadow_copy = 48225f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski reinterpret_cast<char *>((reinterpret_cast<uintptr_t>(mem_info->shadow_copy_base) + map_alignment) & 4823bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski ~(map_alignment - 1)) + 4824bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski start_offset; 48255f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski assert(vk_safe_modulo(reinterpret_cast<uintptr_t>(mem_info->shadow_copy) + mem_info->shadow_pad_size - start_offset, 48265f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski map_alignment) == 0); 48275f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski 48286e17c244b21ce43ac57404a00a0d844039eed363Mark Lobodzinski memset(mem_info->shadow_copy, NoncoherentMemoryFillValue, static_cast<size_t>(2 * mem_info->shadow_pad_size + size)); 48295f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski *ppData = static_cast<char *>(mem_info->shadow_copy) + mem_info->shadow_pad_size; 48305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 48315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 48325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 48335f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski 4834a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis// Verify that state for fence being waited on is appropriate. That is, 48359867daedbf52debc77d6568162ee21e071699b80Chris Forbes// a fence being waited on should not already be signaled and 4836a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis// it should have been submitted on a queue or during acquire next image 483749f6132af865afd5b7f413c91125971ac97c135aChris Forbesstatic inline bool verifyWaitFenceState(layer_data *dev_data, VkFence fence, const char *apiCall) { 483883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 48399b48b44dd917f95b5f34dd629ec4076fc87eb3a2Chris Forbes 48409a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pFence = GetFenceNode(dev_data, fence); 48419b48b44dd917f95b5f34dd629ec4076fc87eb3a2Chris Forbes if (pFence) { 4842cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes if (pFence->state == FENCE_UNSIGNALED) { 484383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, 484483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis reinterpret_cast<uint64_t &>(fence), __LINE__, MEMTRACK_INVALID_FENCE_STATE, "MEM", 4845cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s called for fence 0x%" PRIxLEAST64 4846cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " which has not been submitted on a Queue or during " 484783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis "acquire next image.", 484883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis apiCall, reinterpret_cast<uint64_t &>(fence)); 48495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 48505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 485183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis return skip_call; 48525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 4853a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis 4854b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlisstatic void RetireFence(layer_data *dev_data, VkFence fence) { 48559a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pFence = GetFenceNode(dev_data, fence); 4856b3ecd4c1fb44a2e65dfc13256afa9150aabde1d4Chris Forbes if (pFence->signaler.first != VK_NULL_HANDLE) { 485725002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Fence signaller is a queue -- use this as proof that prior operations on that queue have completed. 48589a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis RetireWorkOnQueue(dev_data, GetQueueState(dev_data, pFence->signaler.first), pFence->signaler.second); 4859bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski } else { 486025002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Fence signaller is the WSI. We're not tracking what the WSI op actually /was/ in CV yet, but we need to mark 486125002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // the fence as retired. 4862d4513979120463171eb479cdded9336eb9944da1Chris Forbes pFence->state = FENCE_RETIRED; 4863d4513979120463171eb479cdded9336eb9944da1Chris Forbes } 4864b3ecd4c1fb44a2e65dfc13256afa9150aabde1d4Chris Forbes} 4865b3ecd4c1fb44a2e65dfc13256afa9150aabde1d4Chris Forbes 4866accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlisstatic bool PreCallValidateWaitForFences(layer_data *dev_data, uint32_t fence_count, const VkFence *fences) { 4867cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.wait_for_fences) return false; 4868accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis bool skip = false; 4869accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis for (uint32_t i = 0; i < fence_count; i++) { 4870accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis skip |= verifyWaitFenceState(dev_data, fences[i], "vkWaitForFences"); 4871b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis skip |= VerifyQueueStateToFence(dev_data, fences[i]); 4872accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis } 4873accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis return skip; 4874accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis} 4875accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis 4876b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlisstatic void PostCallRecordWaitForFences(layer_data *dev_data, uint32_t fence_count, const VkFence *fences, VkBool32 wait_all) { 4877b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis // When we know that all fences are complete we can clean/remove their CBs 4878accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis if ((VK_TRUE == wait_all) || (1 == fence_count)) { 4879accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis for (uint32_t i = 0; i < fence_count; i++) { 4880b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis RetireFence(dev_data, fences[i]); 4881accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis } 4882accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis } 4883accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis // NOTE : Alternate case not handled here is when some fences have completed. In 4884accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis // this case for app to guarantee which fences completed it will have to call 4885b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis // vkGetFenceStatus() at which point we'll clean/remove their CBs if complete. 4886accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis} 4887accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis 4888bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL WaitForFences(VkDevice device, uint32_t fenceCount, const VkFence *pFences, VkBool32 waitAll, 4889bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski uint64_t timeout) { 489056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 48915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Verify fence status of submitted fences 4892b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 4893accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis bool skip = PreCallValidateWaitForFences(dev_data, fenceCount, pFences); 4894b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 4895cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 4896a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis 48974a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.WaitForFences(device, fenceCount, pFences, waitAll, timeout); 4898414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller 48995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (result == VK_SUCCESS) { 4900b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.lock(); 4901b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis PostCallRecordWaitForFences(dev_data, fenceCount, pFences, waitAll); 4902b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 49035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 49045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 49055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 49065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4907f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlisstatic bool PreCallValidateGetFenceStatus(layer_data *dev_data, VkFence fence) { 4908cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.get_fence_state) return false; 4909f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis return verifyWaitFenceState(dev_data, fence, "vkGetFenceStatus"); 4910f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis} 4911f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis 4912b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlisstatic void PostCallRecordGetFenceStatus(layer_data *dev_data, VkFence fence) { RetireFence(dev_data, fence); } 4913f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis 491489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL GetFenceStatus(VkDevice device, VkFence fence) { 491556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 4916b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 4917f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis bool skip = PreCallValidateGetFenceStatus(dev_data, fence); 4918b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 4919cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 4920a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis 49214a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.GetFenceStatus(device, fence); 49225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (result == VK_SUCCESS) { 4923f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis lock.lock(); 4924b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis PostCallRecordGetFenceStatus(dev_data, fence); 4925f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis lock.unlock(); 49265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 49275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 49285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 49295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 49303b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlisstatic void PostCallRecordGetDeviceQueue(layer_data *dev_data, uint32_t q_family_index, VkQueue queue) { 49313b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis // Add queue to tracking set only if it is new 49323b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis auto result = dev_data->queues.emplace(queue); 49333b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis if (result.second == true) { 493436c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlis QUEUE_STATE *queue_state = &dev_data->queueMap[queue]; 49353b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis queue_state->queue = queue; 49363b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis queue_state->queueFamilyIndex = q_family_index; 49373b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis queue_state->seq = 0; 49383b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis } 49393b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis} 49403b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis 4941bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL GetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue *pQueue) { 494256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 49434a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue); 4944b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 4945b376edacad6f7ab3fcc0a914e9b1673a9fcd5143Mark Lobodzinski 49463b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis PostCallRecordGetDeviceQueue(dev_data, queueFamilyIndex, *pQueue); 49475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 49485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 494936c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlisstatic bool PreCallValidateQueueWaitIdle(layer_data *dev_data, VkQueue queue, QUEUE_STATE **queue_state) { 49509a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *queue_state = GetQueueState(dev_data, queue); 4951cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.queue_wait_idle) return false; 4952e0cec9ec6dd3cfd83345cabba55ec021681801dbTobin Ehlis return VerifyQueueStateToSeq(dev_data, *queue_state, (*queue_state)->seq + (*queue_state)->submissions.size()); 49534273a1c157585a645dca4c960086032793899d05Tobin Ehlis} 49544273a1c157585a645dca4c960086032793899d05Tobin Ehlis 495536c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlisstatic void PostCallRecordQueueWaitIdle(layer_data *dev_data, QUEUE_STATE *queue_state) { 4956e0cec9ec6dd3cfd83345cabba55ec021681801dbTobin Ehlis RetireWorkOnQueue(dev_data, queue_state, queue_state->seq + queue_state->submissions.size()); 49574273a1c157585a645dca4c960086032793899d05Tobin Ehlis} 49584273a1c157585a645dca4c960086032793899d05Tobin Ehlis 495989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL QueueWaitIdle(VkQueue queue) { 496056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map); 496136c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlis QUEUE_STATE *queue_state = nullptr; 49629867daedbf52debc77d6568162ee21e071699b80Chris Forbes std::unique_lock<std::mutex> lock(global_lock); 49634273a1c157585a645dca4c960086032793899d05Tobin Ehlis bool skip = PreCallValidateQueueWaitIdle(dev_data, queue, &queue_state); 49649867daedbf52debc77d6568162ee21e071699b80Chris Forbes lock.unlock(); 4965cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 49664a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.QueueWaitIdle(queue); 49674273a1c157585a645dca4c960086032793899d05Tobin Ehlis if (VK_SUCCESS == result) { 4968e0cec9ec6dd3cfd83345cabba55ec021681801dbTobin Ehlis lock.lock(); 4969e0cec9ec6dd3cfd83345cabba55ec021681801dbTobin Ehlis PostCallRecordQueueWaitIdle(dev_data, queue_state); 4970e0cec9ec6dd3cfd83345cabba55ec021681801dbTobin Ehlis lock.unlock(); 49714273a1c157585a645dca4c960086032793899d05Tobin Ehlis } 49725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 49735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 49745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 49758767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlisstatic bool PreCallValidateDeviceWaitIdle(layer_data *dev_data) { 4976cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.device_wait_idle) return false; 49778767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis bool skip = false; 49788767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis for (auto &queue : dev_data->queueMap) { 49798767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis skip |= VerifyQueueStateToSeq(dev_data, &queue.second, queue.second.seq + queue.second.submissions.size()); 49808767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis } 49818767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis return skip; 49828767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis} 49838767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis 49848767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlisstatic void PostCallRecordDeviceWaitIdle(layer_data *dev_data) { 49858767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis for (auto &queue : dev_data->queueMap) { 49868767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis RetireWorkOnQueue(dev_data, &queue.second, queue.second.seq + queue.second.submissions.size()); 49878767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis } 49888767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis} 49898767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis 499089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL DeviceWaitIdle(VkDevice device) { 499156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 4992b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 49938767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis bool skip = PreCallValidateDeviceWaitIdle(dev_data); 4994b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 4995cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 49964a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.DeviceWaitIdle(device); 49978767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis if (VK_SUCCESS == result) { 49988767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis lock.lock(); 49998767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis PostCallRecordDeviceWaitIdle(dev_data); 50008767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis lock.unlock(); 50018767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis } 50025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 50035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 50045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 50051d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlisstatic bool PreCallValidateDestroyFence(layer_data *dev_data, VkFence fence, FENCE_NODE **fence_node, VK_OBJECT *obj_struct) { 50069a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *fence_node = GetFenceNode(dev_data, fence); 50071d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis *obj_struct = {reinterpret_cast<uint64_t &>(fence), VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT}; 5008cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_fence) return false; 50091d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis bool skip = false; 50101d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis if (*fence_node) { 50111d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis if ((*fence_node)->state == FENCE_INFLIGHT) { 50121d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, 5013208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis (uint64_t)(fence), __LINE__, VALIDATION_ERROR_00173, "DS", "Fence 0x%" PRIx64 " is in use. %s", 5014208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis (uint64_t)(fence), validation_error_map[VALIDATION_ERROR_00173]); 50151d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis } 50161d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis } 50171d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis return skip; 50181d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis} 50191d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis 50201d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlisstatic void PostCallRecordDestroyFence(layer_data *dev_data, VkFence fence) { dev_data->fenceMap.erase(fence); } 50211d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis 502289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL DestroyFence(VkDevice device, VkFence fence, const VkAllocationCallbacks *pAllocator) { 502356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 50241d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis // Common data objects used pre & post call 50251d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis FENCE_NODE *fence_node = nullptr; 50261d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis VK_OBJECT obj_struct; 5027b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 50281d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis bool skip = PreCallValidateDestroyFence(dev_data, fence, &fence_node, &obj_struct); 50291344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis 50301d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis if (!skip) { 50311d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis lock.unlock(); 50324a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyFence(device, fence, pAllocator); 50331d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis lock.lock(); 50341d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis PostCallRecordDestroyFence(dev_data, fence); 50351d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis } 50365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 50375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5038c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlisstatic bool PreCallValidateDestroySemaphore(layer_data *dev_data, VkSemaphore semaphore, SEMAPHORE_NODE **sema_node, 5039c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis VK_OBJECT *obj_struct) { 50409a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *sema_node = GetSemaphoreNode(dev_data, semaphore); 5041c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis *obj_struct = {reinterpret_cast<uint64_t &>(semaphore), VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT}; 5042cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_semaphore) return false; 5043c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis bool skip = false; 5044c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis if (*sema_node) { 5045c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis skip |= ValidateObjectNotInUse(dev_data, *sema_node, *obj_struct, VALIDATION_ERROR_00199); 5046c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis } 5047c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis return skip; 5048c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis} 5049c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis 5050c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlisstatic void PostCallRecordDestroySemaphore(layer_data *dev_data, VkSemaphore sema) { dev_data->semaphoreMap.erase(sema); } 5051c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis 5052bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroySemaphore(VkDevice device, VkSemaphore semaphore, const VkAllocationCallbacks *pAllocator) { 505356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 5054c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis SEMAPHORE_NODE *sema_node; 5055c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis VK_OBJECT obj_struct; 5056e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 5057c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis bool skip = PreCallValidateDestroySemaphore(dev_data, semaphore, &sema_node, &obj_struct); 5058eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis if (!skip) { 5059eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis lock.unlock(); 50604a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroySemaphore(device, semaphore, pAllocator); 5061c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis lock.lock(); 5062c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis PostCallRecordDestroySemaphore(dev_data, semaphore); 506399d938c90c2f000ee73fb13513dacf84ffa5651fMark Mueller } 50645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 50655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 50664710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlisstatic bool PreCallValidateDestroyEvent(layer_data *dev_data, VkEvent event, EVENT_STATE **event_state, VK_OBJECT *obj_struct) { 50679a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *event_state = GetEventNode(dev_data, event); 506894165f5005d1fa37801d49067fe7751789b89d27Tobin Ehlis *obj_struct = {reinterpret_cast<uint64_t &>(event), VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT}; 5069cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_event) return false; 5070d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis bool skip = false; 5071d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis if (*event_state) { 5072d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis skip |= ValidateObjectNotInUse(dev_data, *event_state, *obj_struct, VALIDATION_ERROR_00213); 5073d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis } 5074d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis return skip; 5075d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis} 5076d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis 50774710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlisstatic void PostCallRecordDestroyEvent(layer_data *dev_data, VkEvent event, EVENT_STATE *event_state, VK_OBJECT obj_struct) { 507839c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis invalidateCommandBuffers(dev_data, event_state->cb_bindings, obj_struct); 5079d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis dev_data->eventMap.erase(event); 5080d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis} 5081d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis 508289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL DestroyEvent(VkDevice device, VkEvent event, const VkAllocationCallbacks *pAllocator) { 508356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 50844710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis EVENT_STATE *event_state = nullptr; 5085d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis VK_OBJECT obj_struct; 5086b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 5087d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis bool skip = PreCallValidateDestroyEvent(dev_data, event, &event_state, &obj_struct); 5088f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis if (!skip) { 5089f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis lock.unlock(); 50904a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyEvent(device, event, pAllocator); 5091d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis lock.lock(); 5092405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (event != VK_NULL_HANDLE) { 5093405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyEvent(dev_data, event, event_state, obj_struct); 5094405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 5095f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis } 50965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 50975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 509883c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlisstatic bool PreCallValidateDestroyQueryPool(layer_data *dev_data, VkQueryPool query_pool, QUERY_POOL_NODE **qp_state, 509983c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis VK_OBJECT *obj_struct) { 51009a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *qp_state = GetQueryPoolNode(dev_data, query_pool); 510183c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis *obj_struct = {reinterpret_cast<uint64_t &>(query_pool), VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT}; 5102cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_query_pool) return false; 510383c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis bool skip = false; 510483c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis if (*qp_state) { 510583c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis skip |= ValidateObjectNotInUse(dev_data, *qp_state, *obj_struct, VALIDATION_ERROR_01012); 510683c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis } 510783c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis return skip; 510883c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis} 510983c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis 5110bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic void PostCallRecordDestroyQueryPool(layer_data *dev_data, VkQueryPool query_pool, QUERY_POOL_NODE *qp_state, 5111bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VK_OBJECT obj_struct) { 511283c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis invalidateCommandBuffers(dev_data, qp_state->cb_bindings, obj_struct); 511383c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis dev_data->queryPoolMap.erase(query_pool); 511483c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis} 511583c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis 5116bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyQueryPool(VkDevice device, VkQueryPool queryPool, const VkAllocationCallbacks *pAllocator) { 511756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 511883c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis QUERY_POOL_NODE *qp_state = nullptr; 511983c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis VK_OBJECT obj_struct; 5120ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 512183c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis bool skip = PreCallValidateDestroyQueryPool(dev_data, queryPool, &qp_state, &obj_struct); 5122f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis if (!skip) { 5123f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis lock.unlock(); 51244a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyQueryPool(device, queryPool, pAllocator); 512583c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis lock.lock(); 5126405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (queryPool != VK_NULL_HANDLE) { 5127405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyQueryPool(dev_data, queryPool, qp_state, obj_struct); 5128405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 5129f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis } 51305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 51319fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlisstatic bool PreCallValidateGetQueryPoolResults(layer_data *dev_data, VkQueryPool query_pool, uint32_t first_query, 51329fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis uint32_t query_count, VkQueryResultFlags flags, 51339fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis unordered_map<QueryObject, vector<VkCommandBuffer>> *queries_in_flight) { 51349fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis for (auto cmd_buffer : dev_data->globalInFlightCmdBuffers) { 51359a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb = GetCBNode(dev_data, cmd_buffer); 51369fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis for (auto query_state_pair : cb->queryToStateMap) { 51379fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis (*queries_in_flight)[query_state_pair.first].push_back(cmd_buffer); 51385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 51395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5140cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.get_query_pool_results) return false; 51419fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis bool skip = false; 51429fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis for (uint32_t i = 0; i < query_count; ++i) { 51439fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis QueryObject query = {query_pool, first_query + i}; 51449fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis auto qif_pair = queries_in_flight->find(query); 51459fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis auto query_state_pair = dev_data->queryToStateMap.find(query); 51469fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis if (query_state_pair != dev_data->queryToStateMap.end()) { 5147ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski // Available and in flight 51489fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis if (qif_pair != queries_in_flight->end() && query_state_pair != dev_data->queryToStateMap.end() && 51499fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis query_state_pair->second) { 51509fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis for (auto cmd_buffer : qif_pair->second) { 51519a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb = GetCBNode(dev_data, cmd_buffer); 51529fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis auto query_event_pair = cb->waitedEventsBeforeQueryReset.find(query); 51539fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis if (query_event_pair == cb->waitedEventsBeforeQueryReset.end()) { 51549fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 51559fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, __LINE__, DRAWSTATE_INVALID_QUERY, "DS", 51569fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis "Cannot get query results on queryPool 0x%" PRIx64 " with index %d which is in flight.", 51579fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis (uint64_t)(query_pool), first_query + i); 5158ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski } 5159ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski } 5160ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski // Unavailable and in flight 51619fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis } else if (qif_pair != queries_in_flight->end() && query_state_pair != dev_data->queryToStateMap.end() && 51629fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis !query_state_pair->second) { 5163ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski // TODO : Can there be the same query in use by multiple command buffers in flight? 5164ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski bool make_available = false; 51659fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis for (auto cmd_buffer : qif_pair->second) { 51669a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb = GetCBNode(dev_data, cmd_buffer); 51679fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis make_available |= cb->queryToStateMap[query]; 5168ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski } 5169ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski if (!(((flags & VK_QUERY_RESULT_PARTIAL_BIT) || (flags & VK_QUERY_RESULT_WAIT_BIT)) && make_available)) { 51709fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 51719fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, __LINE__, DRAWSTATE_INVALID_QUERY, "DS", 51729fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis "Cannot get query results on queryPool 0x%" PRIx64 " with index %d which is unavailable.", 51739fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis (uint64_t)(query_pool), first_query + i); 51745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5175ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski // Unavailable 51769fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis } else if (query_state_pair != dev_data->queryToStateMap.end() && !query_state_pair->second) { 51779fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, 51789fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis __LINE__, DRAWSTATE_INVALID_QUERY, "DS", 51799fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis "Cannot get query results on queryPool 0x%" PRIx64 " with index %d which is unavailable.", 51809fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis (uint64_t)(query_pool), first_query + i); 51819fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis // Uninitialized 51829fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis } else if (query_state_pair == dev_data->queryToStateMap.end()) { 51839fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, 51849fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis __LINE__, DRAWSTATE_INVALID_QUERY, "DS", 51859fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis "Cannot get query results on queryPool 0x%" PRIx64 51869fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis " with index %d as data has not been collected for this index.", 51879fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis (uint64_t)(query_pool), first_query + i); 51885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 51895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 51905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 51919fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis return skip; 51929fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis} 51939fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis 51949fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlisstatic void PostCallRecordGetQueryPoolResults(layer_data *dev_data, VkQueryPool query_pool, uint32_t first_query, 51959fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis uint32_t query_count, 51969fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis unordered_map<QueryObject, vector<VkCommandBuffer>> *queries_in_flight) { 51979fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis for (uint32_t i = 0; i < query_count; ++i) { 51989fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis QueryObject query = {query_pool, first_query + i}; 51999fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis auto qif_pair = queries_in_flight->find(query); 52009fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis auto query_state_pair = dev_data->queryToStateMap.find(query); 52019fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis if (query_state_pair != dev_data->queryToStateMap.end()) { 52029fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis // Available and in flight 52039fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis if (qif_pair != queries_in_flight->end() && query_state_pair != dev_data->queryToStateMap.end() && 52049fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis query_state_pair->second) { 52059fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis for (auto cmd_buffer : qif_pair->second) { 52069a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb = GetCBNode(dev_data, cmd_buffer); 52079fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis auto query_event_pair = cb->waitedEventsBeforeQueryReset.find(query); 52089fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis if (query_event_pair != cb->waitedEventsBeforeQueryReset.end()) { 52099fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis for (auto event : query_event_pair->second) { 52109fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis dev_data->eventMap[event].needsSignaled = true; 52119fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis } 52129fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis } 52139fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis } 52149fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis } 52159fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis } 52169fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis } 52179fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis} 52189fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis 52199fdee42cd357379efb9aa27f90beb75d1f824955Tobin EhlisVKAPI_ATTR VkResult VKAPI_CALL GetQueryPoolResults(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, 52209fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis size_t dataSize, void *pData, VkDeviceSize stride, VkQueryResultFlags flags) { 522156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 52229fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis unordered_map<QueryObject, vector<VkCommandBuffer>> queries_in_flight; 52239fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 52249fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis bool skip = PreCallValidateGetQueryPoolResults(dev_data, queryPool, firstQuery, queryCount, flags, &queries_in_flight); 5225b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 5226cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 52279fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis VkResult result = 52289fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis dev_data->dispatch_table.GetQueryPoolResults(device, queryPool, firstQuery, queryCount, dataSize, pData, stride, flags); 52299fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis lock.lock(); 52309fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis PostCallRecordGetQueryPoolResults(dev_data, queryPool, firstQuery, queryCount, &queries_in_flight); 52319fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis lock.unlock(); 52329fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis return result; 52335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 52345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5235825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Return true if given ranges intersect, else false 5236825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Prereq : For both ranges, range->end - range->start > 0. This case should have already resulted 5237825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// in an error so not checking that here 5238825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// pad_ranges bool indicates a linear and non-linear comparison which requires padding 5239825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// In the case where padding is required, if an alias is encountered then a validation error is reported and skip_call 5240825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// may be set by the callback function so caller should merge in skip_call value if padding case is possible. 52412ea938737c34152a86f5e453eaef7f77b45c0ea3Cort Stratton// This check can be skipped by passing skip_checks=true, for call sites outside the validation path. 52422ea938737c34152a86f5e453eaef7f77b45c0ea3Cort Strattonstatic bool rangesIntersect(layer_data const *dev_data, MEMORY_RANGE const *range1, MEMORY_RANGE const *range2, bool *skip_call, 52432ea938737c34152a86f5e453eaef7f77b45c0ea3Cort Stratton bool skip_checks) { 52447dc3fbb89e2dcf3df8fc2e6639a867a959fef3f3Tobin Ehlis *skip_call = false; 5245825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis auto r1_start = range1->start; 5246825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis auto r1_end = range1->end; 5247825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis auto r2_start = range2->start; 5248825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis auto r2_end = range2->end; 5249825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis VkDeviceSize pad_align = 1; 5250825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis if (range1->linear != range2->linear) { 5251825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis pad_align = dev_data->phys_dev_properties.properties.limits.bufferImageGranularity; 5252825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis } 5253cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if ((r1_end & ~(pad_align - 1)) < (r2_start & ~(pad_align - 1))) return false; 5254cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if ((r1_start & ~(pad_align - 1)) > (r2_end & ~(pad_align - 1))) return false; 525547aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski 52562ea938737c34152a86f5e453eaef7f77b45c0ea3Cort Stratton if (!skip_checks && (range1->linear != range2->linear)) { 525753ecec26e80e4d18b57d24ed6eb91a3c9da4b95cTobin Ehlis // In linear vs. non-linear case, warn of aliasing 5258825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis const char *r1_linear_str = range1->linear ? "Linear" : "Non-linear"; 5259825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis const char *r1_type_str = range1->image ? "image" : "buffer"; 5260825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis const char *r2_linear_str = range2->linear ? "linear" : "non-linear"; 5261825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis const char *r2_type_str = range2->image ? "image" : "buffer"; 5262825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis auto obj_type = range1->image ? VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT : VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT; 526353ecec26e80e4d18b57d24ed6eb91a3c9da4b95cTobin Ehlis *skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, obj_type, range1->handle, 0, 526453ecec26e80e4d18b57d24ed6eb91a3c9da4b95cTobin Ehlis MEMTRACK_INVALID_ALIASING, "MEM", "%s %s 0x%" PRIx64 " is aliased with %s %s 0x%" PRIx64 526553ecec26e80e4d18b57d24ed6eb91a3c9da4b95cTobin Ehlis " which may indicate a bug. For further info refer to the " 526653ecec26e80e4d18b57d24ed6eb91a3c9da4b95cTobin Ehlis "Buffer-Image Granularity section of the Vulkan specification. " 526753ecec26e80e4d18b57d24ed6eb91a3c9da4b95cTobin Ehlis "(https://www.khronos.org/registry/vulkan/specs/1.0-extensions/" 526853ecec26e80e4d18b57d24ed6eb91a3c9da4b95cTobin Ehlis "xhtml/vkspec.html#resources-bufferimagegranularity)", 526953ecec26e80e4d18b57d24ed6eb91a3c9da4b95cTobin Ehlis r1_linear_str, r1_type_str, range1->handle, r2_linear_str, r2_type_str, range2->handle); 527047aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski } 5271825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis // Ranges intersect 5272825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis return true; 527347aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski} 5274623548a271287ae55415e45e3c654ee66d4e79ffTobin Ehlis// Simplified rangesIntersect that calls above function to check range1 for intersection with offset & end addresses 5275c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinskibool rangesIntersect(layer_data const *dev_data, MEMORY_RANGE const *range1, VkDeviceSize offset, VkDeviceSize end) { 5276825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis // Create a local MEMORY_RANGE struct to wrap offset/size 5277825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis MEMORY_RANGE range_wrap; 5278825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis // Synch linear with range1 to avoid padding and potential validation error case 5279825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis range_wrap.linear = range1->linear; 5280825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis range_wrap.start = offset; 5281cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis range_wrap.end = end; 5282825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis bool tmp_bool; 52832ea938737c34152a86f5e453eaef7f77b45c0ea3Cort Stratton return rangesIntersect(dev_data, range1, &range_wrap, &tmp_bool, true); 5284825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis} 5285cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis// For given mem_info, set all ranges valid that intersect [offset-end] range 5286cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis// TODO : For ranges where there is no alias, we may want to create new buffer ranges that are valid 5287cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlisstatic void SetMemRangesValid(layer_data const *dev_data, DEVICE_MEM_INFO *mem_info, VkDeviceSize offset, VkDeviceSize end) { 5288cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis bool tmp_bool = false; 5289f6e16b28b808a342cb92768001afa2cfeee08a11Tobin Ehlis MEMORY_RANGE map_range = {}; 5290cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis map_range.linear = true; 5291cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis map_range.start = offset; 5292cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis map_range.end = end; 5293cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis for (auto &handle_range_pair : mem_info->bound_ranges) { 52942ea938737c34152a86f5e453eaef7f77b45c0ea3Cort Stratton if (rangesIntersect(dev_data, &handle_range_pair.second, &map_range, &tmp_bool, false)) { 5295cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis // TODO : WARN here if tmp_bool true? 5296cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis handle_range_pair.second.valid = true; 5297cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis } 5298cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis } 5299cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis} 53000ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton 53010ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Strattonstatic bool ValidateInsertMemoryRange(layer_data const *dev_data, uint64_t handle, DEVICE_MEM_INFO *mem_info, 53020ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton VkDeviceSize memoryOffset, VkMemoryRequirements memRequirements, bool is_image, 53030ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton bool is_linear, const char *api_name) { 53040ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton bool skip = false; 53050ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton 53060ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton MEMORY_RANGE range; 53070ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton range.image = is_image; 53080ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton range.handle = handle; 53090ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton range.linear = is_linear; 53100ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton range.valid = mem_info->global_valid; 53110ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton range.memory = mem_info->mem; 53120ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton range.start = memoryOffset; 53130ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton range.size = memRequirements.size; 53140ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton range.end = memoryOffset + memRequirements.size - 1; 53150ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton range.aliases.clear(); 53160ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton 53170ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton // Check for aliasing problems. 53180ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton for (auto &obj_range_pair : mem_info->bound_ranges) { 53190ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton auto check_range = &obj_range_pair.second; 53200ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton bool intersection_error = false; 53212ea938737c34152a86f5e453eaef7f77b45c0ea3Cort Stratton if (rangesIntersect(dev_data, &range, check_range, &intersection_error, false)) { 53220ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton skip |= intersection_error; 53230ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton range.aliases.insert(check_range); 53240ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton } 53250ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton } 53260ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton 53270ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton if (memoryOffset >= mem_info->alloc_info.allocationSize) { 53280ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton UNIQUE_VALIDATION_ERROR_CODE error_code = is_image ? VALIDATION_ERROR_00805 : VALIDATION_ERROR_00793; 53290ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton skip = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 53300ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton reinterpret_cast<uint64_t &>(mem_info->mem), __LINE__, error_code, "MEM", 53310ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton "In %s, attempting to bind memory (0x%" PRIxLEAST64 ") to object (0x%" PRIxLEAST64 53320ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton "), memoryOffset=0x%" PRIxLEAST64 " must be less than the memory allocation size 0x%" PRIxLEAST64 ". %s", 53330ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton api_name, reinterpret_cast<uint64_t &>(mem_info->mem), handle, memoryOffset, 53340ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton mem_info->alloc_info.allocationSize, validation_error_map[error_code]); 53350ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton } 53360ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton 53370ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton return skip; 53380ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton} 53390ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton 5340825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Object with given handle is being bound to memory w/ given mem_info struct. 5341825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Track the newly bound memory range with given memoryOffset 5342825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Also scan any previous ranges, track aliased ranges with new range, and flag an error if a linear 5343825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// and non-linear range incorrectly overlap. 5344825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Return true if an error is flagged and the user callback returns "true", otherwise false 5345825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// is_image indicates an image object, otherwise handle is for a buffer 5346825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// is_linear indicates a buffer or linear image 53470ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Strattonstatic void InsertMemoryRange(layer_data const *dev_data, uint64_t handle, DEVICE_MEM_INFO *mem_info, VkDeviceSize memoryOffset, 53480ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton VkMemoryRequirements memRequirements, bool is_image, bool is_linear) { 53495360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis MEMORY_RANGE range; 5350825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis 5351825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis range.image = is_image; 535247aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski range.handle = handle; 5353825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis range.linear = is_linear; 5354f541bf53dee6daf82a4c8304354eac599a884d29Tobin Ehlis range.valid = mem_info->global_valid; 5355825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis range.memory = mem_info->mem; 535647aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski range.start = memoryOffset; 5357825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis range.size = memRequirements.size; 535847aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski range.end = memoryOffset + memRequirements.size - 1; 53595360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis range.aliases.clear(); 53605360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis // Update Memory aliasing 536175f4c8cec0996021a4258b9bf920a9e0fea4eac1Tobin 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 53625360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis // inserted into map before loop to get the final ptr, then we may enter loop when not needed & we check range against itself 53635360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis std::unordered_set<MEMORY_RANGE *> tmp_alias_ranges; 5364825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis for (auto &obj_range_pair : mem_info->bound_ranges) { 5365825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis auto check_range = &obj_range_pair.second; 53665360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis bool intersection_error = false; 53672ea938737c34152a86f5e453eaef7f77b45c0ea3Cort Stratton if (rangesIntersect(dev_data, &range, check_range, &intersection_error, true)) { 5368825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis range.aliases.insert(check_range); 53695360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis tmp_alias_ranges.insert(check_range); 5370825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis } 5371825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis } 53725360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis mem_info->bound_ranges[handle] = std::move(range); 53735360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis for (auto tmp_range : tmp_alias_ranges) { 53745360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis tmp_range->aliases.insert(&mem_info->bound_ranges[handle]); 53755360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis } 5376825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis if (is_image) 5377825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis mem_info->bound_images.insert(handle); 5378825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis else 5379825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis mem_info->bound_buffers.insert(handle); 538047aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski} 538147aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski 53820ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Strattonstatic bool ValidateInsertImageMemoryRange(layer_data const *dev_data, VkImage image, DEVICE_MEM_INFO *mem_info, 53830ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton VkDeviceSize mem_offset, VkMemoryRequirements mem_reqs, bool is_linear, 53840ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton const char *api_name) { 53850ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton return ValidateInsertMemoryRange(dev_data, reinterpret_cast<uint64_t &>(image), mem_info, mem_offset, mem_reqs, true, is_linear, 53860ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton api_name); 53870ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton} 53880ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Strattonstatic void InsertImageMemoryRange(layer_data const *dev_data, VkImage image, DEVICE_MEM_INFO *mem_info, VkDeviceSize mem_offset, 53890ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton VkMemoryRequirements mem_reqs, bool is_linear) { 53900ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton InsertMemoryRange(dev_data, reinterpret_cast<uint64_t &>(image), mem_info, mem_offset, mem_reqs, true, is_linear); 5391825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis} 5392825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis 53930ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Strattonstatic bool ValidateInsertBufferMemoryRange(layer_data const *dev_data, VkBuffer buffer, DEVICE_MEM_INFO *mem_info, 53940ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton VkDeviceSize mem_offset, VkMemoryRequirements mem_reqs, const char *api_name) { 53950ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton return ValidateInsertMemoryRange(dev_data, reinterpret_cast<uint64_t &>(buffer), mem_info, mem_offset, mem_reqs, false, true, 53960ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton api_name); 53970ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton} 53980ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Strattonstatic void InsertBufferMemoryRange(layer_data const *dev_data, VkBuffer buffer, DEVICE_MEM_INFO *mem_info, VkDeviceSize mem_offset, 53990ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton VkMemoryRequirements mem_reqs) { 54000ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton InsertMemoryRange(dev_data, reinterpret_cast<uint64_t &>(buffer), mem_info, mem_offset, mem_reqs, false, true); 5401825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis} 5402825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis 5403825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Remove MEMORY_RANGE struct for give handle from bound_ranges of mem_info 5404825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// is_image indicates if handle is for image or buffer 5405825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// This function will also remove the handle-to-index mapping from the appropriate 5406825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// map and clean up any aliases for range being removed. 5407825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlisstatic void RemoveMemoryRange(uint64_t handle, DEVICE_MEM_INFO *mem_info, bool is_image) { 5408825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis auto erase_range = &mem_info->bound_ranges[handle]; 5409825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis for (auto alias_range : erase_range->aliases) { 5410825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis alias_range->aliases.erase(erase_range); 541147aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski } 54125360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis erase_range->aliases.clear(); 5413825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis mem_info->bound_ranges.erase(handle); 54141cba4e1b5940c6818572e05dcad5a3a47fafbc9eTobin Ehlis if (is_image) { 5415825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis mem_info->bound_images.erase(handle); 54161cba4e1b5940c6818572e05dcad5a3a47fafbc9eTobin Ehlis } else { 5417825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis mem_info->bound_buffers.erase(handle); 54181cba4e1b5940c6818572e05dcad5a3a47fafbc9eTobin Ehlis } 541947aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski} 542047aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski 5421842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinskivoid RemoveBufferMemoryRange(uint64_t handle, DEVICE_MEM_INFO *mem_info) { RemoveMemoryRange(handle, mem_info, false); } 5422825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis 54238c59133586421be878d393799b30044497f77727Mark Lobodzinskivoid RemoveImageMemoryRange(uint64_t handle, DEVICE_MEM_INFO *mem_info) { RemoveMemoryRange(handle, mem_info, true); } 5424825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis 5425bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyBuffer(VkDevice device, VkBuffer buffer, const VkAllocationCallbacks *pAllocator) { 542656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 5427e1056daefb39e3a3fed0088874725c56a1359e54Tobin Ehlis BUFFER_STATE *buffer_state = nullptr; 5428e1056daefb39e3a3fed0088874725c56a1359e54Tobin Ehlis VK_OBJECT obj_struct; 5429b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 5430e1056daefb39e3a3fed0088874725c56a1359e54Tobin Ehlis bool skip = PreCallValidateDestroyBuffer(dev_data, buffer, &buffer_state, &obj_struct); 5431e1056daefb39e3a3fed0088874725c56a1359e54Tobin Ehlis if (!skip) { 5432b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 54334a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyBuffer(device, buffer, pAllocator); 5434e1056daefb39e3a3fed0088874725c56a1359e54Tobin Ehlis lock.lock(); 5435405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (buffer != VK_NULL_HANDLE) { 5436405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyBuffer(dev_data, buffer, buffer_state, obj_struct); 5437405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 543847aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski } 54395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 54405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5441bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyBufferView(VkDevice device, VkBufferView bufferView, const VkAllocationCallbacks *pAllocator) { 544256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 5443f61017735c3291a2665487f2bac310578fc60a68Tobin Ehlis // Common data objects used pre & post call 54448e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis BUFFER_VIEW_STATE *buffer_view_state = nullptr; 54458e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis VK_OBJECT obj_struct; 5446a123662876eebfa844faa65ae3f071d3d77618ebTobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 54478e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis // Validate state before calling down chain, update common data if we'll be calling down chain 54488e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis bool skip = PreCallValidateDestroyBufferView(dev_data, bufferView, &buffer_view_state, &obj_struct); 544938e26abbaa884eb48bfec4ddb4e0ae2c90634e06Tobin Ehlis if (!skip) { 545038e26abbaa884eb48bfec4ddb4e0ae2c90634e06Tobin Ehlis lock.unlock(); 54514a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyBufferView(device, bufferView, pAllocator); 54528e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis lock.lock(); 5453405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (bufferView != VK_NULL_HANDLE) { 5454405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyBufferView(dev_data, bufferView, buffer_view_state, obj_struct); 5455405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 54565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 54575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 54585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 54592a0dd15a44bf665c97a3ff6adcbe7fe5853cdf60Tobin EhlisVKAPI_ATTR void VKAPI_CALL DestroyImage(VkDevice device, VkImage image, const VkAllocationCallbacks *pAllocator) { 546056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 54611facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis IMAGE_STATE *image_state = nullptr; 54622a0dd15a44bf665c97a3ff6adcbe7fe5853cdf60Tobin Ehlis VK_OBJECT obj_struct; 54632a0dd15a44bf665c97a3ff6adcbe7fe5853cdf60Tobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 54642a0dd15a44bf665c97a3ff6adcbe7fe5853cdf60Tobin Ehlis bool skip = PreCallValidateDestroyImage(dev_data, image, &image_state, &obj_struct); 54652a0dd15a44bf665c97a3ff6adcbe7fe5853cdf60Tobin Ehlis if (!skip) { 5466f940225c9e5e3e14b3f5a32d3ea360b585614600Tobin Ehlis lock.unlock(); 54674a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyImage(device, image, pAllocator); 54682a0dd15a44bf665c97a3ff6adcbe7fe5853cdf60Tobin Ehlis lock.lock(); 5469405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (image != VK_NULL_HANDLE) { 5470405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyImage(dev_data, image, image_state, obj_struct); 5471405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 54725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 54735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 54745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 54754261f1e2c91c90ce040ab36a13c9d92f6e988f10Mark Lobodzinskistatic bool ValidateMemoryTypes(const layer_data *dev_data, const DEVICE_MEM_INFO *mem_info, const uint32_t memory_type_bits, 5476f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen const char *funcName, UNIQUE_VALIDATION_ERROR_CODE msgCode) { 54774261f1e2c91c90ce040ab36a13c9d92f6e988f10Mark Lobodzinski bool skip_call = false; 5478de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis if (((1 << mem_info->alloc_info.memoryTypeIndex) & memory_type_bits) == 0) { 5479f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen skip_call = 5480f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 5481f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen reinterpret_cast<const uint64_t &>(mem_info->mem), __LINE__, msgCode, "MT", 5482f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen "%s(): MemoryRequirements->memoryTypeBits (0x%X) for this object type are not compatible with the memory " 5483f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen "type (0x%X) of this memory object 0x%" PRIx64 ". %s", 5484f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen funcName, memory_type_bits, mem_info->alloc_info.memoryTypeIndex, 5485f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen reinterpret_cast<const uint64_t &>(mem_info->mem), validation_error_map[msgCode]); 54864261f1e2c91c90ce040ab36a13c9d92f6e988f10Mark Lobodzinski } 54874261f1e2c91c90ce040ab36a13c9d92f6e988f10Mark Lobodzinski return skip_call; 54884261f1e2c91c90ce040ab36a13c9d92f6e988f10Mark Lobodzinski} 54894261f1e2c91c90ce040ab36a13c9d92f6e988f10Mark Lobodzinski 5490160335c453ec51cc48bdef78e8befdb3c86ff292Cort Strattonstatic bool PreCallValidateBindBufferMemory(layer_data *dev_data, VkBuffer buffer, BUFFER_STATE *buffer_state, VkDeviceMemory mem, 5491160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton VkDeviceSize memoryOffset) { 54929207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton bool skip = false; 54935cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis if (buffer_state) { 5494160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton std::unique_lock<std::mutex> lock(global_lock); 54959207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton // Track objects tied to memory 54969207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton uint64_t buffer_handle = reinterpret_cast<uint64_t &>(buffer); 5497c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton skip = ValidateSetMemBinding(dev_data, mem, buffer_handle, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, "vkBindBufferMemory()"); 54982eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis if (!buffer_state->memory_requirements_checked) { 54992eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis // There's not an explicit requirement in the spec to call vkGetBufferMemoryRequirements() prior to calling 55009207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton // BindBufferMemory, but it's implied in that memory being bound must conform with VkMemoryRequirements from 55019207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton // vkGetBufferMemoryRequirements() 55029207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, 55039207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton buffer_handle, __LINE__, DRAWSTATE_INVALID_BUFFER, "DS", 55049207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton "vkBindBufferMemory(): Binding memory to buffer 0x%" PRIxLEAST64 55059207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton " but vkGetBufferMemoryRequirements() has not been called on that buffer.", 55069207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton buffer_handle); 55072eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis // Make the call for them so we can verify the state 55082eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis lock.unlock(); 55099207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton dev_data->dispatch_table.GetBufferMemoryRequirements(dev_data->device, buffer, &buffer_state->requirements); 55102eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis lock.lock(); 55112eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis } 551247aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski 55130ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton // Validate bound memory range information 55149a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto mem_info = GetMemObjInfo(dev_data, mem); 551557fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis if (mem_info) { 55160ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton skip |= ValidateInsertBufferMemoryRange(dev_data, buffer, mem_info, memoryOffset, buffer_state->requirements, 55170ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton "vkBindBufferMemory()"); 55189207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton skip |= ValidateMemoryTypes(dev_data, mem_info, buffer_state->requirements.memoryTypeBits, "vkBindBufferMemory()", 55199207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton VALIDATION_ERROR_00797); 552047aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski } 552147aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski 55222c905c8b5aca814df6c680348145ca48885f9f69Dustin Graves // Validate memory requirements alignment 55232eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis if (vk_safe_modulo(memoryOffset, buffer_state->requirements.alignment) != 0) { 5524f60e41965223825191505eebc96491bb52e494a2Cort Stratton skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, 5525f60e41965223825191505eebc96491bb52e494a2Cort Stratton buffer_handle, __LINE__, VALIDATION_ERROR_02174, "DS", 55269207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton "vkBindBufferMemory(): memoryOffset is 0x%" PRIxLEAST64 55279207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton " but must be an integer multiple of the " 55289207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton "VkMemoryRequirements::alignment value 0x%" PRIxLEAST64 55299207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton ", returned from a call to vkGetBufferMemoryRequirements with buffer. %s", 55309207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton memoryOffset, buffer_state->requirements.alignment, validation_error_map[VALIDATION_ERROR_02174]); 55312c905c8b5aca814df6c680348145ca48885f9f69Dustin Graves } 5532ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller 5533160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton // Validate memory requirements size 5534160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton if (buffer_state->requirements.size > (mem_info->alloc_info.allocationSize - memoryOffset)) { 5535160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, 5536160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton buffer_handle, __LINE__, VALIDATION_ERROR_02175, "DS", 5537160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton "vkBindBufferMemory(): memory size minus memoryOffset is 0x%" PRIxLEAST64 5538160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton " but must be at least as large as " 5539160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton "VkMemoryRequirements::size value 0x%" PRIxLEAST64 5540160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton ", returned from a call to vkGetBufferMemoryRequirements with buffer. %s", 5541160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton mem_info->alloc_info.allocationSize - memoryOffset, buffer_state->requirements.size, 5542160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton validation_error_map[VALIDATION_ERROR_02175]); 5543160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton } 5544160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton 55452c905c8b5aca814df6c680348145ca48885f9f69Dustin Graves // Validate device limits alignments 5546ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller static const VkBufferUsageFlagBits usage_list[3] = { 5547ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller static_cast<VkBufferUsageFlagBits>(VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT), 5548bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT}; 5549bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski static const char *memory_type[3] = {"texel", "uniform", "storage"}; 5550bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski static const char *offset_name[3] = {"minTexelBufferOffsetAlignment", "minUniformBufferOffsetAlignment", 5551bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "minStorageBufferOffsetAlignment"}; 5552cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski 55539207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton // TODO: vk_validation_stats.py cannot abide braces immediately preceding or following a validation error enum 5554cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // clang-format off 55550ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton static const UNIQUE_VALIDATION_ERROR_CODE msgCode[3] = { VALIDATION_ERROR_00794, VALIDATION_ERROR_00795, 55560ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton VALIDATION_ERROR_00796 }; 5557cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // clang-format on 5558ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller 5559ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller // Keep this one fresh! 5560ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller const VkDeviceSize offset_requirement[3] = { 5561ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller dev_data->phys_dev_properties.properties.limits.minTexelBufferOffsetAlignment, 5562ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller dev_data->phys_dev_properties.properties.limits.minUniformBufferOffsetAlignment, 5563bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski dev_data->phys_dev_properties.properties.limits.minStorageBufferOffsetAlignment}; 55648718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis VkBufferUsageFlags usage = dev_data->bufferMap[buffer].get()->createInfo.usage; 5565ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller 5566ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller for (int i = 0; i < 3; i++) { 5567ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller if (usage & usage_list[i]) { 5568ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller if (vk_safe_modulo(memoryOffset, offset_requirement[i]) != 0) { 55699207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton skip |= log_msg( 5570f60e41965223825191505eebc96491bb52e494a2Cort Stratton dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, buffer_handle, 5571cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, msgCode[i], "DS", "vkBindBufferMemory(): %s memoryOffset is 0x%" PRIxLEAST64 5572cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " but must be a multiple of " 5573cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "device limit %s 0x%" PRIxLEAST64 ". %s", 5574cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski memory_type[i], memoryOffset, offset_name[i], offset_requirement[i], validation_error_map[msgCode[i]]); 5575ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller } 55762c905c8b5aca814df6c680348145ca48885f9f69Dustin Graves } 55772c905c8b5aca814df6c680348145ca48885f9f69Dustin Graves } 55785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 55799207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton return skip; 55809207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton} 55819207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton 5582160335c453ec51cc48bdef78e8befdb3c86ff292Cort Strattonstatic void PostCallRecordBindBufferMemory(layer_data *dev_data, VkBuffer buffer, BUFFER_STATE *buffer_state, VkDeviceMemory mem, 5583160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton VkDeviceSize memoryOffset) { 55849207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton if (buffer_state) { 5585160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton std::unique_lock<std::mutex> lock(global_lock); 55860ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton // Track bound memory range information 55870ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton auto mem_info = GetMemObjInfo(dev_data, mem); 55880ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton if (mem_info) { 55890ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton InsertBufferMemoryRange(dev_data, buffer, mem_info, memoryOffset, buffer_state->requirements); 55900ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton } 55910ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton 5592c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton // Track objects tied to memory 5593c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton uint64_t buffer_handle = reinterpret_cast<uint64_t &>(buffer); 5594c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton SetMemBinding(dev_data, mem, buffer_handle, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, "vkBindBufferMemory()"); 5595c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton 55969207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton buffer_state->binding.mem = mem; 55979207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton buffer_state->binding.offset = memoryOffset; 55989207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton buffer_state->binding.size = buffer_state->requirements.size; 55999207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton } 56009207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton} 56019207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton 56029207132ef623d47fcbdfeb9ebc796eade35a2f4cCort StrattonVKAPI_ATTR VkResult VKAPI_CALL BindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory mem, VkDeviceSize memoryOffset) { 56039207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 56049207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 5605160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton auto buffer_state = GetBufferState(dev_data, buffer); 5606160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton bool skip = PreCallValidateBindBufferMemory(dev_data, buffer, buffer_state, mem, memoryOffset); 56079207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton if (!skip) { 56084a0754042cf090e131e9e769d8a3633c228625beChris Forbes result = dev_data->dispatch_table.BindBufferMemory(device, buffer, mem, memoryOffset); 56099207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton if (result == VK_SUCCESS) { 5610160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton PostCallRecordBindBufferMemory(dev_data, buffer, buffer_state, mem, memoryOffset); 56119207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton } 56125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 56135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 56145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 56155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5616bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL GetBufferMemoryRequirements(VkDevice device, VkBuffer buffer, 5617bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkMemoryRequirements *pMemoryRequirements) { 561856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 561915caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis dev_data->dispatch_table.GetBufferMemoryRequirements(device, buffer, pMemoryRequirements); 56209a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto buffer_state = GetBufferState(dev_data, buffer); 562115caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis if (buffer_state) { 562215caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis buffer_state->requirements = *pMemoryRequirements; 56232eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis buffer_state->memory_requirements_checked = true; 562415caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis } 56255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 56265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5627bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL GetImageMemoryRequirements(VkDevice device, VkImage image, VkMemoryRequirements *pMemoryRequirements) { 562856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 562915caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis dev_data->dispatch_table.GetImageMemoryRequirements(device, image, pMemoryRequirements); 56309a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_state = GetImageState(dev_data, image); 563115caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis if (image_state) { 563215caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis image_state->requirements = *pMemoryRequirements; 56332eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis image_state->memory_requirements_checked = true; 563415caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis } 56355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 5636593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 5637bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyImageView(VkDevice device, VkImageView imageView, const VkAllocationCallbacks *pAllocator) { 563856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 5639f61017735c3291a2665487f2bac310578fc60a68Tobin Ehlis // Common data objects used pre & post call 5640f61017735c3291a2665487f2bac310578fc60a68Tobin Ehlis IMAGE_VIEW_STATE *image_view_state = nullptr; 5641f61017735c3291a2665487f2bac310578fc60a68Tobin Ehlis VK_OBJECT obj_struct; 5642a123662876eebfa844faa65ae3f071d3d77618ebTobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 5643f61017735c3291a2665487f2bac310578fc60a68Tobin Ehlis bool skip = PreCallValidateDestroyImageView(dev_data, imageView, &image_view_state, &obj_struct); 5644d85c42a6c1d6ad7a6f684c5bd793aab482b7705cTobin Ehlis if (!skip) { 5645d85c42a6c1d6ad7a6f684c5bd793aab482b7705cTobin Ehlis lock.unlock(); 56464a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyImageView(device, imageView, pAllocator); 5647f61017735c3291a2665487f2bac310578fc60a68Tobin Ehlis lock.lock(); 5648405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (imageView != VK_NULL_HANDLE) { 5649405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyImageView(dev_data, imageView, image_view_state, obj_struct); 5650405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 5651d85c42a6c1d6ad7a6f684c5bd793aab482b7705cTobin Ehlis } 56525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 56535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5654bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyShaderModule(VkDevice device, VkShaderModule shaderModule, 5655bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator) { 565656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 5657918c283ac4f8c604b79abd0c8b5706d2a7352a34Chris Forbes 5658b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 565951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->shaderModuleMap.erase(shaderModule); 5660b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 5661918c283ac4f8c604b79abd0c8b5706d2a7352a34Chris Forbes 566251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->dispatch_table.DestroyShaderModule(device, shaderModule, pAllocator); 56635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 56645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 56654c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlisstatic bool PreCallValidateDestroyPipeline(layer_data *dev_data, VkPipeline pipeline, PIPELINE_STATE **pipeline_state, 56668bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis VK_OBJECT *obj_struct) { 566794165f5005d1fa37801d49067fe7751789b89d27Tobin Ehlis *pipeline_state = getPipelineState(dev_data, pipeline); 566894165f5005d1fa37801d49067fe7751789b89d27Tobin Ehlis *obj_struct = {reinterpret_cast<uint64_t &>(pipeline), VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT}; 5669cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_pipeline) return false; 56708bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis bool skip = false; 56718bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis if (*pipeline_state) { 56721803032f91d772ff3589c9f5a51ade5b299ba538Tobin Ehlis skip |= ValidateObjectNotInUse(dev_data, *pipeline_state, *obj_struct, VALIDATION_ERROR_00555); 56738bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis } 56748bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis return skip; 56758bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis} 56768bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis 56774c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlisstatic void PostCallRecordDestroyPipeline(layer_data *dev_data, VkPipeline pipeline, PIPELINE_STATE *pipeline_state, 56788bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis VK_OBJECT obj_struct) { 56798bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis // Any bound cmd buffers are now invalid 568039c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis invalidateCommandBuffers(dev_data, pipeline_state->cb_bindings, obj_struct); 56818bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis dev_data->pipelineMap.erase(pipeline); 56828bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis} 56838bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis 5684bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyPipeline(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks *pAllocator) { 568556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 56864c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis PIPELINE_STATE *pipeline_state = nullptr; 56878bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis VK_OBJECT obj_struct; 5688e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 56898bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis bool skip = PreCallValidateDestroyPipeline(dev_data, pipeline, &pipeline_state, &obj_struct); 5690f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis if (!skip) { 5691f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis lock.unlock(); 56924a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyPipeline(device, pipeline, pAllocator); 56938bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis lock.lock(); 5694405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (pipeline != VK_NULL_HANDLE) { 5695405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyPipeline(dev_data, pipeline, pipeline_state, obj_struct); 5696405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 5697f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis } 56985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 56995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5700bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyPipelineLayout(VkDevice device, VkPipelineLayout pipelineLayout, 5701bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator) { 570256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 5703e28cddb35c63274c13873b9a7060ad43b255c6f1Tobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 57046792ea7cc0ce5fa64b7bd6c946460608cbda91c7Tobin Ehlis dev_data->pipelineLayoutMap.erase(pipelineLayout); 5705e28cddb35c63274c13873b9a7060ad43b255c6f1Tobin Ehlis lock.unlock(); 5706e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis 57074a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyPipelineLayout(device, pipelineLayout, pAllocator); 57085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 57095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5710d31a44af6da568692a73201825459689c9431867Tobin Ehlisstatic bool PreCallValidateDestroySampler(layer_data *dev_data, VkSampler sampler, SAMPLER_STATE **sampler_state, 5711806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis VK_OBJECT *obj_struct) { 57129a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *sampler_state = GetSamplerState(dev_data, sampler); 571394165f5005d1fa37801d49067fe7751789b89d27Tobin Ehlis *obj_struct = {reinterpret_cast<uint64_t &>(sampler), VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT}; 5714cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_sampler) return false; 5715806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis bool skip = false; 5716806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis if (*sampler_state) { 5717806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis skip |= ValidateObjectNotInUse(dev_data, *sampler_state, *obj_struct, VALIDATION_ERROR_00837); 5718806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis } 5719806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis return skip; 5720806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis} 5721806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis 5722d31a44af6da568692a73201825459689c9431867Tobin Ehlisstatic void PostCallRecordDestroySampler(layer_data *dev_data, VkSampler sampler, SAMPLER_STATE *sampler_state, 5723806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis VK_OBJECT obj_struct) { 5724806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis // Any bound cmd buffers are now invalid 5725cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (sampler_state) invalidateCommandBuffers(dev_data, sampler_state->cb_bindings, obj_struct); 5726806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis dev_data->samplerMap.erase(sampler); 5727806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis} 5728806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis 5729bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroySampler(VkDevice device, VkSampler sampler, const VkAllocationCallbacks *pAllocator) { 573056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 5731d31a44af6da568692a73201825459689c9431867Tobin Ehlis SAMPLER_STATE *sampler_state = nullptr; 5732806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis VK_OBJECT obj_struct; 573356f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 5734806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis bool skip = PreCallValidateDestroySampler(dev_data, sampler, &sampler_state, &obj_struct); 5735f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis if (!skip) { 5736f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis lock.unlock(); 57374a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroySampler(device, sampler, pAllocator); 5738806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis lock.lock(); 5739405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (sampler != VK_NULL_HANDLE) { 5740405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroySampler(dev_data, sampler, sampler_state, obj_struct); 5741405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 5742f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis } 57435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 57445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 574579c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlisstatic void PostCallRecordDestroyDescriptorSetLayout(layer_data *dev_data, VkDescriptorSetLayout ds_layout) { 574679c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlis dev_data->descriptorSetLayoutMap.erase(ds_layout); 574779c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlis} 574879c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlis 5749bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyDescriptorSetLayout(VkDevice device, VkDescriptorSetLayout descriptorSetLayout, 5750bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator) { 575156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 575279c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlis dev_data->dispatch_table.DestroyDescriptorSetLayout(device, descriptorSetLayout, pAllocator); 575379c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 575479c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlis PostCallRecordDestroyDescriptorSetLayout(dev_data, descriptorSetLayout); 57555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 57565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5757c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlisstatic bool PreCallValidateDestroyDescriptorPool(layer_data *dev_data, VkDescriptorPool pool, 5758a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis DESCRIPTOR_POOL_STATE **desc_pool_state, VK_OBJECT *obj_struct) { 57599a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *desc_pool_state = GetDescriptorPoolState(dev_data, pool); 576094165f5005d1fa37801d49067fe7751789b89d27Tobin Ehlis *obj_struct = {reinterpret_cast<uint64_t &>(pool), VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT}; 5761cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_descriptor_pool) return false; 5762c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis bool skip = false; 5763c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis if (*desc_pool_state) { 57641803032f91d772ff3589c9f5a51ade5b299ba538Tobin Ehlis skip |= ValidateObjectNotInUse(dev_data, *desc_pool_state, *obj_struct, VALIDATION_ERROR_00901); 5765c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis } 5766c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis return skip; 5767c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis} 5768c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis 5769c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlisstatic void PostCallRecordDestroyDescriptorPool(layer_data *dev_data, VkDescriptorPool descriptorPool, 5770a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis DESCRIPTOR_POOL_STATE *desc_pool_state, VK_OBJECT obj_struct) { 5771c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis // Any bound cmd buffers are now invalid 577239c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis invalidateCommandBuffers(dev_data, desc_pool_state->cb_bindings, obj_struct); 5773c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis // Free sets that were in this pool 5774c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis for (auto ds : desc_pool_state->sets) { 5775c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis freeDescriptorSet(dev_data, ds); 5776c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis } 5777c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis dev_data->descriptorPoolMap.erase(descriptorPool); 5778c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis} 5779c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis 5780bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, 5781bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator) { 578256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 5783a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis DESCRIPTOR_POOL_STATE *desc_pool_state = nullptr; 5784c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis VK_OBJECT obj_struct; 5785c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 5786c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis bool skip = PreCallValidateDestroyDescriptorPool(dev_data, descriptorPool, &desc_pool_state, &obj_struct); 5787c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis if (!skip) { 5788c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis lock.unlock(); 5789c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis dev_data->dispatch_table.DestroyDescriptorPool(device, descriptorPool, pAllocator); 5790c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis lock.lock(); 5791405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (descriptorPool != VK_NULL_HANDLE) { 5792405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyDescriptorPool(dev_data, descriptorPool, desc_pool_state, obj_struct); 5793405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 5794c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis } 57955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 5796bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis// Verify cmdBuffer in given cb_node is not in global in-flight set, and return skip_call result 5797bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis// If this is a secondary command buffer, then make sure its primary is also in-flight 5798bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis// If primary is not in-flight, then remove secondary from global in-flight set 5799bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis// This function is only valid at a point when cmdBuffer is being reset or freed 5800cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlisstatic bool checkCommandBufferInFlight(layer_data *dev_data, const GLOBAL_CB_NODE *cb_node, const char *action, 5801cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlis UNIQUE_VALIDATION_ERROR_CODE error_code) { 5802bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis bool skip_call = false; 5803bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis if (dev_data->globalInFlightCmdBuffers.count(cb_node->commandBuffer)) { 5804bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis // Primary CB or secondary where primary is also in-flight is an error 5805bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis if ((cb_node->createInfo.level != VK_COMMAND_BUFFER_LEVEL_SECONDARY) || 5806bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis (dev_data->globalInFlightCmdBuffers.count(cb_node->primaryCommandBuffer))) { 5807cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlis skip_call |= 5808cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 5809cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlis reinterpret_cast<const uint64_t &>(cb_node->commandBuffer), __LINE__, error_code, "DS", 5810226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "Attempt to %s command buffer (0x%p) which is in use. %s", action, cb_node->commandBuffer, 5811226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis validation_error_map[error_code]); 5812bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis } 5813bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis } 5814bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis return skip_call; 5815bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis} 5816a964cad279f9749cd9ebfc7555247ff3bff26d53Chris Forbes 5817bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis// Iterate over all cmdBuffers in given commandPool and verify that each is not in use 5818cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlisstatic bool checkCommandBuffersInFlight(layer_data *dev_data, COMMAND_POOL_NODE *pPool, const char *action, 5819cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlis UNIQUE_VALIDATION_ERROR_CODE error_code) { 5820bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis bool skip_call = false; 5821a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes for (auto cmd_buffer : pPool->commandBuffers) { 5822a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes if (dev_data->globalInFlightCmdBuffers.count(cmd_buffer)) { 58239a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis skip_call |= checkCommandBufferInFlight(dev_data, GetCBNode(dev_data, cmd_buffer), action, error_code); 5824bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis } 5825bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis } 5826bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis return skip_call; 5827bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis} 58285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5829a01b5eb150981aad061238e64b173d0da8c11140Chris Forbesstatic void clearCommandBuffersInFlight(layer_data *dev_data, COMMAND_POOL_NODE *pPool) { 5830a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes for (auto cmd_buffer : pPool->commandBuffers) { 5831a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes dev_data->globalInFlightCmdBuffers.erase(cmd_buffer); 5832a964cad279f9749cd9ebfc7555247ff3bff26d53Chris Forbes } 5833a964cad279f9749cd9ebfc7555247ff3bff26d53Chris Forbes} 5834a964cad279f9749cd9ebfc7555247ff3bff26d53Chris Forbes 5835bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL FreeCommandBuffers(VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount, 5836bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkCommandBuffer *pCommandBuffers) { 583756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 58385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool skip_call = false; 5839b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 5840c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes 58415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < commandBufferCount; i++) { 58429a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, pCommandBuffers[i]); 58435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Delete CB information structure, and remove from commandBufferMap 58449f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis if (cb_node) { 5845cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlis skip_call |= checkCommandBufferInFlight(dev_data, cb_node, "free", VALIDATION_ERROR_00096); 5846c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes } 5847c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes } 5848c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes 5849cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip_call) return; 5850c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes 58519a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pPool = GetCommandPoolNode(dev_data, commandPool); 5852c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes for (uint32_t i = 0; i < commandBufferCount; i++) { 58539a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, pCommandBuffers[i]); 5854c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes // Delete CB information structure, and remove from commandBufferMap 58559f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis if (cb_node) { 58569f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis dev_data->globalInFlightCmdBuffers.erase(cb_node->commandBuffer); 58575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // reset prior to delete for data clean-up 58589f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis resetCB(dev_data, cb_node->commandBuffer); 58599f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis dev_data->commandBufferMap.erase(cb_node->commandBuffer); 58609f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis delete cb_node; 58615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 58625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 58635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Remove commandBuffer reference from commandPoolMap 5864c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes pPool->commandBuffers.remove(pCommandBuffers[i]); 58655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5866b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 5867e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis 58684a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.FreeCommandBuffers(device, commandPool, commandBufferCount, pCommandBuffers); 58695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 58705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 587189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateCommandPool(VkDevice device, const VkCommandPoolCreateInfo *pCreateInfo, 5872bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkCommandPool *pCommandPool) { 587356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 58745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 58754a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateCommandPool(device, pCreateInfo, pAllocator, pCommandPool); 58765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 58775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 5878b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 58795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->commandPoolMap[*pCommandPool].createFlags = pCreateInfo->flags; 58805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->commandPoolMap[*pCommandPool].queueFamilyIndex = pCreateInfo->queueFamilyIndex; 58815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 58825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 58835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 58845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 588589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateQueryPool(VkDevice device, const VkQueryPoolCreateInfo *pCreateInfo, 588689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkQueryPool *pQueryPool) { 588756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 58880c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis bool skip = false; 58890c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis if (pCreateInfo && pCreateInfo->queryType == VK_QUERY_TYPE_PIPELINE_STATISTICS) { 58900c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis if (!dev_data->enabled_features.pipelineStatisticsQuery) { 58910c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, 58920c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis __LINE__, VALIDATION_ERROR_01006, "DS", 58930c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis "Query pool with type VK_QUERY_TYPE_PIPELINE_STATISTICS created on a device " 58940c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis "with VkDeviceCreateInfo.pEnabledFeatures.pipelineStatisticsQuery == VK_FALSE. %s", 58950c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis validation_error_map[VALIDATION_ERROR_01006]); 58960c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis } 58970c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis } 58980c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis 58990c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 59000c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis if (!skip) { 59010c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis result = dev_data->dispatch_table.CreateQueryPool(device, pCreateInfo, pAllocator, pQueryPool); 59020c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis } 59035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (result == VK_SUCCESS) { 5904b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 5905eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis QUERY_POOL_NODE *qp_node = &dev_data->queryPoolMap[*pQueryPool]; 5906eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis qp_node->createInfo = *pCreateInfo; 59075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 59085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 59095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 59105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 59115f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlisstatic bool PreCallValidateDestroyCommandPool(layer_data *dev_data, VkCommandPool pool, COMMAND_POOL_NODE **cp_state) { 59129a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *cp_state = GetCommandPoolNode(dev_data, pool); 5913cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_command_pool) return false; 59145f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis bool skip = false; 59155f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis if (*cp_state) { 59165f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis // Verify that command buffers in pool are complete (not in-flight) 59175f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis skip |= checkCommandBuffersInFlight(dev_data, *cp_state, "destroy command pool with", VALIDATION_ERROR_00077); 59185f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis } 59195f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis return skip; 59205f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis} 59215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 59225f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlisstatic void PostCallRecordDestroyCommandPool(layer_data *dev_data, VkCommandPool pool, COMMAND_POOL_NODE *cp_state) { 59239f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis // Must remove cmdpool from cmdpoolmap, after removing all cmdbuffers in its list from the commandBufferMap 59245f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis clearCommandBuffersInFlight(dev_data, cp_state); 59255f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis for (auto cb : cp_state->commandBuffers) { 5926a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes clear_cmd_buf_and_mem_references(dev_data, cb); 59279a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, cb); 5928d61de0e68063faa169a9a632f811c9c9adec9897Tobin Ehlis // Remove references to this cb_node prior to delete 5929d61de0e68063faa169a9a632f811c9c9adec9897Tobin Ehlis // TODO : Need better solution here, resetCB? 59307165385f3a39f1f951f3a6a9a06ed2cce4642b6dMark Lobodzinski for (auto obj : cb_node->object_bindings) { 59317165385f3a39f1f951f3a6a9a06ed2cce4642b6dMark Lobodzinski removeCommandBufferBinding(dev_data, &obj, cb_node); 59327165385f3a39f1f951f3a6a9a06ed2cce4642b6dMark Lobodzinski } 5933d61de0e68063faa169a9a632f811c9c9adec9897Tobin Ehlis for (auto framebuffer : cb_node->framebuffers) { 59349a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto fb_state = GetFramebufferState(dev_data, framebuffer); 5935cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (fb_state) fb_state->cb_bindings.erase(cb_node); 5936d61de0e68063faa169a9a632f811c9c9adec9897Tobin Ehlis } 5937cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski dev_data->commandBufferMap.erase(cb); // Remove this command buffer 5938cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski delete cb_node; // delete CB info structure 5939a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes } 59405f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis dev_data->commandPoolMap.erase(pool); 59415f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis} 5942e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis 59435f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis// Destroy commandPool along with all of the commandBuffers allocated from that pool 59445f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin EhlisVKAPI_ATTR void VKAPI_CALL DestroyCommandPool(VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks *pAllocator) { 594556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 59465f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis COMMAND_POOL_NODE *cp_state = nullptr; 59475f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 59485f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis bool skip = PreCallValidateDestroyCommandPool(dev_data, commandPool, &cp_state); 59495f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis if (!skip) { 59505f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis lock.unlock(); 59515f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis dev_data->dispatch_table.DestroyCommandPool(device, commandPool, pAllocator); 59525f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis lock.lock(); 5953405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (commandPool != VK_NULL_HANDLE) { 5954405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyCommandPool(dev_data, commandPool, cp_state); 5955405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 59565f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis } 59575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 59585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5959bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL ResetCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolResetFlags flags) { 596056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 596183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 5962400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis 59631ec6311a8537f4467db08eacbd762ebaa87e70b0Chris Forbes std::unique_lock<std::mutex> lock(global_lock); 59649a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pPool = GetCommandPoolNode(dev_data, commandPool); 5965cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlis skip_call |= checkCommandBuffersInFlight(dev_data, pPool, "reset command pool with", VALIDATION_ERROR_00072); 59661ec6311a8537f4467db08eacbd762ebaa87e70b0Chris Forbes lock.unlock(); 5967a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes 5968cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip_call) return VK_ERROR_VALIDATION_FAILED_EXT; 59695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 59704a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.ResetCommandPool(device, commandPool, flags); 59715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 59725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Reset all of the CBs allocated from this pool 59735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 59741ec6311a8537f4467db08eacbd762ebaa87e70b0Chris Forbes lock.lock(); 5975a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes clearCommandBuffersInFlight(dev_data, pPool); 5976a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes for (auto cmdBuffer : pPool->commandBuffers) { 5977a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes resetCB(dev_data, cmdBuffer); 59785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 59791ec6311a8537f4467db08eacbd762ebaa87e70b0Chris Forbes lock.unlock(); 59805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 59815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 59825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 59835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 598489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL ResetFences(VkDevice device, uint32_t fenceCount, const VkFence *pFences) { 598556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 598683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 5987b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 59885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < fenceCount; ++i) { 59899a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pFence = GetFenceNode(dev_data, pFences[i]); 5990090da73358f71ba026e2474a822fecf55267d166Chris Forbes if (pFence && pFence->state == FENCE_INFLIGHT) { 599183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, 59924527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton reinterpret_cast<const uint64_t &>(pFences[i]), __LINE__, VALIDATION_ERROR_00183, "DS", 59934527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton "Fence 0x%" PRIx64 " is in use. %s", reinterpret_cast<const uint64_t &>(pFences[i]), 59944527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton validation_error_map[VALIDATION_ERROR_00183]); 59955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 59965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5997b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 5998090da73358f71ba026e2474a822fecf55267d166Chris Forbes 5999cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip_call) return VK_ERROR_VALIDATION_FAILED_EXT; 6000090da73358f71ba026e2474a822fecf55267d166Chris Forbes 60014a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.ResetFences(device, fenceCount, pFences); 6002090da73358f71ba026e2474a822fecf55267d166Chris Forbes 6003090da73358f71ba026e2474a822fecf55267d166Chris Forbes if (result == VK_SUCCESS) { 6004090da73358f71ba026e2474a822fecf55267d166Chris Forbes lock.lock(); 6005090da73358f71ba026e2474a822fecf55267d166Chris Forbes for (uint32_t i = 0; i < fenceCount; ++i) { 60069a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pFence = GetFenceNode(dev_data, pFences[i]); 6007090da73358f71ba026e2474a822fecf55267d166Chris Forbes if (pFence) { 6008090da73358f71ba026e2474a822fecf55267d166Chris Forbes pFence->state = FENCE_UNSIGNALED; 6009090da73358f71ba026e2474a822fecf55267d166Chris Forbes } 6010090da73358f71ba026e2474a822fecf55267d166Chris Forbes } 6011090da73358f71ba026e2474a822fecf55267d166Chris Forbes lock.unlock(); 6012090da73358f71ba026e2474a822fecf55267d166Chris Forbes } 6013090da73358f71ba026e2474a822fecf55267d166Chris Forbes 60145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 60155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 60165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6017e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis// For given cb_nodes, invalidate them and track object causing invalidation 60180a4087f99558069e9f6a437ff2dbb5a9c1c22ccaTobin Ehlisvoid invalidateCommandBuffers(const layer_data *dev_data, std::unordered_set<GLOBAL_CB_NODE *> const &cb_nodes, VK_OBJECT obj) { 6019e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis for (auto cb_node : cb_nodes) { 602039c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis if (cb_node->state == CB_RECORDING) { 602139c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 6022fefa20333f94ea75877cca53d0631542cd9d0432Tobin Ehlis (uint64_t)(cb_node->commandBuffer), __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER, "DS", 6023226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "Invalidating a command buffer that's currently being recorded: 0x%p.", cb_node->commandBuffer); 602439c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis } 6025e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis cb_node->state = CB_INVALID; 6026e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis cb_node->broken_bindings.push_back(obj); 6027e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis } 6028e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis} 6029e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis 6030c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlisstatic bool PreCallValidateDestroyFramebuffer(layer_data *dev_data, VkFramebuffer framebuffer, 6031c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis FRAMEBUFFER_STATE **framebuffer_state, VK_OBJECT *obj_struct) { 60329a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *framebuffer_state = GetFramebufferState(dev_data, framebuffer); 603394165f5005d1fa37801d49067fe7751789b89d27Tobin Ehlis *obj_struct = {reinterpret_cast<uint64_t &>(framebuffer), VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT}; 6034cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_framebuffer) return false; 6035728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis bool skip = false; 6036728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis if (*framebuffer_state) { 6037728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis skip |= ValidateObjectNotInUse(dev_data, *framebuffer_state, *obj_struct, VALIDATION_ERROR_00422); 6038728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis } 6039728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis return skip; 6040728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis} 6041728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis 6042c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlisstatic void PostCallRecordDestroyFramebuffer(layer_data *dev_data, VkFramebuffer framebuffer, FRAMEBUFFER_STATE *framebuffer_state, 6043728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis VK_OBJECT obj_struct) { 604439c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis invalidateCommandBuffers(dev_data, framebuffer_state->cb_bindings, obj_struct); 6045728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis dev_data->frameBufferMap.erase(framebuffer); 6046728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis} 6047728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis 6048bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyFramebuffer(VkDevice device, VkFramebuffer framebuffer, const VkAllocationCallbacks *pAllocator) { 604956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 6050c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis FRAMEBUFFER_STATE *framebuffer_state = nullptr; 6051728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis VK_OBJECT obj_struct; 6052b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 6053728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis bool skip = PreCallValidateDestroyFramebuffer(dev_data, framebuffer, &framebuffer_state, &obj_struct); 6054728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis if (!skip) { 6055728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis lock.unlock(); 6056728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis dev_data->dispatch_table.DestroyFramebuffer(device, framebuffer, pAllocator); 6057728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis lock.lock(); 6058405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (framebuffer != VK_NULL_HANDLE) { 6059405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyFramebuffer(dev_data, framebuffer, framebuffer_state, obj_struct); 6060405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 60615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 60625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 60635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 60640ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlisstatic bool PreCallValidateDestroyRenderPass(layer_data *dev_data, VkRenderPass render_pass, RENDER_PASS_STATE **rp_state, 60650ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis VK_OBJECT *obj_struct) { 60669a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *rp_state = GetRenderPassState(dev_data, render_pass); 606794165f5005d1fa37801d49067fe7751789b89d27Tobin Ehlis *obj_struct = {reinterpret_cast<uint64_t &>(render_pass), VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT}; 6068cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_renderpass) return false; 60690ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis bool skip = false; 60700ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis if (*rp_state) { 60710ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis skip |= ValidateObjectNotInUse(dev_data, *rp_state, *obj_struct, VALIDATION_ERROR_00393); 60720ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis } 60730ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis return skip; 60740ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis} 60750ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis 60760ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlisstatic void PostCallRecordDestroyRenderPass(layer_data *dev_data, VkRenderPass render_pass, RENDER_PASS_STATE *rp_state, 60770ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis VK_OBJECT obj_struct) { 607839c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis invalidateCommandBuffers(dev_data, rp_state->cb_bindings, obj_struct); 60790ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis dev_data->renderPassMap.erase(render_pass); 60800ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis} 60810ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis 6082bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyRenderPass(VkDevice device, VkRenderPass renderPass, const VkAllocationCallbacks *pAllocator) { 608356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 60840ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis RENDER_PASS_STATE *rp_state = nullptr; 60850ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis VK_OBJECT obj_struct; 6086e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 60870ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis bool skip = PreCallValidateDestroyRenderPass(dev_data, renderPass, &rp_state, &obj_struct); 6088a9fbfe0c622e9fa4b56ddd015ed4c3c409020c2eTobin Ehlis if (!skip) { 6089a9fbfe0c622e9fa4b56ddd015ed4c3c409020c2eTobin Ehlis lock.unlock(); 60904a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyRenderPass(device, renderPass, pAllocator); 60910ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis lock.lock(); 6092405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (renderPass != VK_NULL_HANDLE) { 6093405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyRenderPass(dev_data, renderPass, rp_state, obj_struct); 6094405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 6095a9fbfe0c622e9fa4b56ddd015ed4c3c409020c2eTobin Ehlis } 60965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 60975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 609889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateBuffer(VkDevice device, const VkBufferCreateInfo *pCreateInfo, 609989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkBuffer *pBuffer) { 610056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 61013683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski std::unique_lock<std::mutex> lock(global_lock); 61023683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski bool skip = PreCallValidateCreateBuffer(dev_data, pCreateInfo); 61033683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski lock.unlock(); 61043683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski 61053683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 61064a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateBuffer(device, pCreateInfo, pAllocator, pBuffer); 61075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 61085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 61093683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski lock.lock(); 61103683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski PostCallRecordCreateBuffer(dev_data, pCreateInfo, pBuffer); 61113683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski lock.unlock(); 61125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 61135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 61145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 61155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 611689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateBufferView(VkDevice device, const VkBufferViewCreateInfo *pCreateInfo, 611789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkBufferView *pView) { 611856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 61198c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young std::unique_lock<std::mutex> lock(global_lock); 61208c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young bool skip_call = PreCallValidateCreateBufferView(dev_data, pCreateInfo); 61218c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young lock.unlock(); 6122cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip_call) return VK_ERROR_VALIDATION_FAILED_EXT; 61234a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateBufferView(device, pCreateInfo, pAllocator, pView); 61245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 61258c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young lock.lock(); 61263683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski PostCallRecordCreateBufferView(dev_data, pCreateInfo, pView); 61278c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young lock.unlock(); 61285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 61295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 61305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 61315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 61328dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski// Access helper functions for external modules 6133d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinskiconst VkFormatProperties *GetFormatProperties(core_validation::layer_data *device_data, VkFormat format) { 6134d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski VkFormatProperties *format_properties = new VkFormatProperties; 6135d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski instance_layer_data *instance_data = 6136d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski GetLayerDataPtr(get_dispatch_key(device_data->instance_data->instance), instance_layer_data_map); 6137d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski instance_data->dispatch_table.GetPhysicalDeviceFormatProperties(device_data->physical_device, format, format_properties); 6138d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski return format_properties; 61398dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski} 61408dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski 6141d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinskiconst VkImageFormatProperties *GetImageFormatProperties(core_validation::layer_data *device_data, VkFormat format, 6142d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski VkImageType image_type, VkImageTiling tiling, VkImageUsageFlags usage, 6143d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski VkImageCreateFlags flags) { 6144d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski VkImageFormatProperties *image_format_properties = new VkImageFormatProperties; 6145d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski instance_layer_data *instance_data = 6146d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski GetLayerDataPtr(get_dispatch_key(device_data->instance_data->instance), instance_layer_data_map); 6147d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski instance_data->dispatch_table.GetPhysicalDeviceImageFormatProperties(device_data->physical_device, format, image_type, tiling, 6148d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski usage, flags, image_format_properties); 6149d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski return image_format_properties; 61508dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski} 61518dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski 61527a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlisconst debug_report_data *GetReportData(const core_validation::layer_data *device_data) { return device_data->report_data; } 61538dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski 61548dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinskiconst VkPhysicalDeviceProperties *GetPhysicalDeviceProperties(core_validation::layer_data *device_data) { 61558dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski return &device_data->phys_dev_props; 61568dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski} 61578dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski 61588c59133586421be878d393799b30044497f77727Mark Lobodzinskiconst CHECK_DISABLED *GetDisables(core_validation::layer_data *device_data) { return &device_data->instance_data->disabled; } 61598c59133586421be878d393799b30044497f77727Mark Lobodzinski 61608c59133586421be878d393799b30044497f77727Mark Lobodzinskistd::unordered_map<VkImage, std::unique_ptr<IMAGE_STATE>> *GetImageMap(core_validation::layer_data *device_data) { 61618c59133586421be878d393799b30044497f77727Mark Lobodzinski return &device_data->imageMap; 61628c59133586421be878d393799b30044497f77727Mark Lobodzinski} 61638c59133586421be878d393799b30044497f77727Mark Lobodzinski 61648c59133586421be878d393799b30044497f77727Mark Lobodzinskistd::unordered_map<VkImage, std::vector<ImageSubresourcePair>> *GetImageSubresourceMap(core_validation::layer_data *device_data) { 61658c59133586421be878d393799b30044497f77727Mark Lobodzinski return &device_data->imageSubresourceMap; 61668c59133586421be878d393799b30044497f77727Mark Lobodzinski} 61678c59133586421be878d393799b30044497f77727Mark Lobodzinski 61688c59133586421be878d393799b30044497f77727Mark Lobodzinskistd::unordered_map<ImageSubresourcePair, IMAGE_LAYOUT_NODE> *GetImageLayoutMap(layer_data *device_data) { 61698c59133586421be878d393799b30044497f77727Mark Lobodzinski return &device_data->imageLayoutMap; 61708c59133586421be878d393799b30044497f77727Mark Lobodzinski} 61718c59133586421be878d393799b30044497f77727Mark Lobodzinski 61723683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinskistd::unordered_map<VkBuffer, std::unique_ptr<BUFFER_STATE>> *GetBufferMap(layer_data *device_data) { 61733683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski return &device_data->bufferMap; 61743683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski} 61753683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski 61763683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinskistd::unordered_map<VkBufferView, std::unique_ptr<BUFFER_VIEW_STATE>> *GetBufferViewMap(layer_data *device_data) { 61773683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski return &device_data->bufferViewMap; 61783683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski} 61793683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski 61801c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinskistd::unordered_map<VkImageView, std::unique_ptr<IMAGE_VIEW_STATE>> *GetImageViewMap(layer_data *device_data) { 61811c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski return &device_data->imageViewMap; 61821c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski} 61831c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski 6184d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinskiconst PHYS_DEV_PROPERTIES_NODE *GetPhysDevProperties(const layer_data *device_data) { 61856a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski return &device_data->phys_dev_properties; 61866a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski} 61876a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski 61885f3e7c34de87353f38bbcd79e12de8af4a9e7695Mark Lobodzinskiconst VkPhysicalDeviceFeatures *GetEnabledFeatures(const layer_data *device_data) { 61895f3e7c34de87353f38bbcd79e12de8af4a9e7695Mark Lobodzinski return &device_data->enabled_features; 61905f3e7c34de87353f38bbcd79e12de8af4a9e7695Mark Lobodzinski} 61915f3e7c34de87353f38bbcd79e12de8af4a9e7695Mark Lobodzinski 61920e2296e24065d02615ee87561bbb80af414a1ddfMike Schuchardtconst devExts *GetDeviceExtensions(const layer_data *device_data) { return &device_data->device_extensions; } 61930e2296e24065d02615ee87561bbb80af414a1ddfMike Schuchardt 619489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo, 619589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkImage *pImage) { 61968dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 619756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 61988dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski bool skip = PreCallValidateCreateImage(dev_data, pCreateInfo, pAllocator, pImage); 61998dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski if (!skip) { 62008dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski result = dev_data->dispatch_table.CreateImage(device, pCreateInfo, pAllocator, pImage); 62018dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski } 62025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 6203b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 6204920311b6aa5614a545cad59521770d0898a75d65Mark Lobodzinski PostCallRecordCreateImage(dev_data, pCreateInfo, pImage); 62055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 62065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 62075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 62085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 62098c07a094dc9cc4afb6b62181f341c12b9e969041Mark YoungVKAPI_ATTR VkResult VKAPI_CALL CreateImageView(VkDevice device, const VkImageViewCreateInfo *pCreateInfo, 62108c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young const VkAllocationCallbacks *pAllocator, VkImageView *pView) { 621156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 62128c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young std::unique_lock<std::mutex> lock(global_lock); 6213e3effabf8e97cae8e006477806ceaca62e4f2ce7Tobin Ehlis bool skip = PreCallValidateCreateImageView(dev_data, pCreateInfo); 62148c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young lock.unlock(); 6215cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 62164a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateImageView(device, pCreateInfo, pAllocator, pView); 62175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 62188c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young lock.lock(); 621979fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis PostCallRecordCreateImageView(dev_data, pCreateInfo, *pView); 62208c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young lock.unlock(); 62215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6222bb6624cb996175d8945190886a200e720b3871efChris Forbes 62235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 62245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 62255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6226bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateFence(VkDevice device, const VkFenceCreateInfo *pCreateInfo, 6227bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkFence *pFence) { 622856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 62294a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateFence(device, pCreateInfo, pAllocator, pFence); 62305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 6231b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 6232a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis auto &fence_node = dev_data->fenceMap[*pFence]; 62338988ad37ea5a054ff2ae3cbe4b767ae6c13cf48bChris Forbes fence_node.fence = *pFence; 6234a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis fence_node.createInfo = *pCreateInfo; 6235cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes fence_node.state = (pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT) ? FENCE_RETIRED : FENCE_UNSIGNALED; 62365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 62375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 62385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 62395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 62405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// TODO handle pipeline caches 624189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreatePipelineCache(VkDevice device, const VkPipelineCacheCreateInfo *pCreateInfo, 624289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkPipelineCache *pPipelineCache) { 624356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 62444a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreatePipelineCache(device, pCreateInfo, pAllocator, pPipelineCache); 62455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 62465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 62475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6248bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyPipelineCache(VkDevice device, VkPipelineCache pipelineCache, 6249bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator) { 625056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 62514a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyPipelineCache(device, pipelineCache, pAllocator); 62525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 62535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6254bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL GetPipelineCacheData(VkDevice device, VkPipelineCache pipelineCache, size_t *pDataSize, 6255bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski void *pData) { 625656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 62574a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.GetPipelineCacheData(device, pipelineCache, pDataSize, pData); 62585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 62595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 62605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6261bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL MergePipelineCaches(VkDevice device, VkPipelineCache dstCache, uint32_t srcCacheCount, 6262bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkPipelineCache *pSrcCaches) { 626356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 62644a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.MergePipelineCaches(device, dstCache, srcCacheCount, pSrcCaches); 62655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 62665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 62675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 62683d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis// utility function to set collective state for pipeline 62694c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlisvoid set_pipeline_state(PIPELINE_STATE *pPipe) { 62703d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis // If any attachment used by this pipeline has blendEnable, set top-level blendEnable 62713d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis if (pPipe->graphicsPipelineCI.pColorBlendState) { 62723d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis for (size_t i = 0; i < pPipe->attachments.size(); ++i) { 62733d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis if (VK_TRUE == pPipe->attachments[i].blendEnable) { 62743d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis if (((pPipe->attachments[i].dstAlphaBlendFactor >= VK_BLEND_FACTOR_CONSTANT_COLOR) && 62753d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis (pPipe->attachments[i].dstAlphaBlendFactor <= VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA)) || 62763d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis ((pPipe->attachments[i].dstColorBlendFactor >= VK_BLEND_FACTOR_CONSTANT_COLOR) && 62773d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis (pPipe->attachments[i].dstColorBlendFactor <= VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA)) || 62783d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis ((pPipe->attachments[i].srcAlphaBlendFactor >= VK_BLEND_FACTOR_CONSTANT_COLOR) && 62793d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis (pPipe->attachments[i].srcAlphaBlendFactor <= VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA)) || 62803d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis ((pPipe->attachments[i].srcColorBlendFactor >= VK_BLEND_FACTOR_CONSTANT_COLOR) && 62813d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis (pPipe->attachments[i].srcColorBlendFactor <= VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA))) { 62823d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis pPipe->blendConstantsEnabled = true; 62833d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 62843d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 62853d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 62863d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 62873d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis} 62883d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis 6289daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinskibool validate_dual_src_blend_feature(layer_data *device_data, PIPELINE_STATE *pipe_state) { 6290daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski bool skip = false; 6291daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski if (pipe_state->graphicsPipelineCI.pColorBlendState) { 6292daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski for (size_t i = 0; i < pipe_state->attachments.size(); ++i) { 6293daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski if (!device_data->enabled_features.dualSrcBlend) { 6294daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski if ((pipe_state->attachments[i].dstAlphaBlendFactor == VK_BLEND_FACTOR_SRC1_COLOR) || 6295daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski (pipe_state->attachments[i].dstAlphaBlendFactor == VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR) || 6296daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski (pipe_state->attachments[i].dstAlphaBlendFactor == VK_BLEND_FACTOR_SRC1_ALPHA) || 6297daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski (pipe_state->attachments[i].dstAlphaBlendFactor == VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA) || 6298daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski (pipe_state->attachments[i].srcAlphaBlendFactor == VK_BLEND_FACTOR_SRC1_COLOR) || 6299daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski (pipe_state->attachments[i].srcAlphaBlendFactor == VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR) || 6300daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski (pipe_state->attachments[i].srcAlphaBlendFactor == VK_BLEND_FACTOR_SRC1_ALPHA) || 6301daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski (pipe_state->attachments[i].srcAlphaBlendFactor == VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA)) { 6302daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski skip |= 6303daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 6304daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski reinterpret_cast<uint64_t &>(pipe_state->pipeline), __LINE__, DRAWSTATE_INVALID_FEATURE, "DS", 6305daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski "CmdBindPipeline: vkPipeline (0x%" PRIxLEAST64 ") attachment[" PRINTF_SIZE_T_SPECIFIER 6306daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski "] has a dual-source blend factor but this device feature is not enabled.", 6307daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski reinterpret_cast<uint64_t &>(pipe_state->pipeline), i); 6308daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski } 6309daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski } 6310daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski } 6311daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski } 6312daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski return skip; 6313daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski} 6314daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski 631548b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinskistatic bool PreCallCreateGraphicsPipelines(layer_data *device_data, uint32_t count, 631648b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinski const VkGraphicsPipelineCreateInfo *create_infos, vector<PIPELINE_STATE *> &pipe_state) { 631748b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinski bool skip = false; 6318bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski instance_layer_data *instance_data = 631956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis GetLayerDataPtr(get_dispatch_key(device_data->instance_data->instance), instance_layer_data_map); 632048b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinski 632148b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinski for (uint32_t i = 0; i < count; i++) { 632248b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinski skip |= verifyPipelineCreateState(device_data, pipe_state, i); 632378b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski if (create_infos[i].pVertexInputState != NULL) { 632478b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski for (uint32_t j = 0; j < create_infos[i].pVertexInputState->vertexAttributeDescriptionCount; j++) { 632578b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski VkFormat format = create_infos[i].pVertexInputState->pVertexAttributeDescriptions[j].format; 632678b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski // Internal call to get format info. Still goes through layers, could potentially go directly to ICD. 632778b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski VkFormatProperties properties; 632878b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski instance_data->dispatch_table.GetPhysicalDeviceFormatProperties(device_data->physical_device, format, &properties); 632978b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski if ((properties.bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) == 0) { 633078b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski skip |= log_msg( 633178b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 633278b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski __LINE__, VALIDATION_ERROR_01413, "IMAGE", 633378b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski "vkCreateGraphicsPipelines: pCreateInfo[%d].pVertexInputState->vertexAttributeDescriptions[%d].format " 633478b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski "(%s) is not a supported vertex buffer format. %s", 633578b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski i, j, string_VkFormat(format), validation_error_map[VALIDATION_ERROR_01413]); 633678b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski } 633778b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski } 633878b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski } 633948b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinski } 634048b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinski return skip; 634148b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinski} 634248b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinski 6343bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count, 6344bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkGraphicsPipelineCreateInfo *pCreateInfos, 6345bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines) { 63465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODO What to do with pipelineCache? 63475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // The order of operations here is a little convoluted but gets the job done 63484c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis // 1. Pipeline create state is first shadowed into PIPELINE_STATE struct 63495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // 2. Create state is then validated (which uses flags setup during shadowing) 63505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // 3. If everything looks good, we'll then create the pipeline and add NODE to pipelineMap 635142486a20f07b16f0c5361cdc00fd789b07b1989aMark Lobodzinski bool skip = false; 63525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODO : Improve this data struct w/ unique_ptrs so cleanup below is automatic 635342486a20f07b16f0c5361cdc00fd789b07b1989aMark Lobodzinski vector<PIPELINE_STATE *> pipe_state(count); 635456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 63555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 63565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t i = 0; 6357b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 63585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 63595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (i = 0; i < count; i++) { 636042486a20f07b16f0c5361cdc00fd789b07b1989aMark Lobodzinski pipe_state[i] = new PIPELINE_STATE; 636142486a20f07b16f0c5361cdc00fd789b07b1989aMark Lobodzinski pipe_state[i]->initGraphicsPipeline(&pCreateInfos[i]); 63629a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis pipe_state[i]->render_pass_ci.initialize(GetRenderPassState(dev_data, pCreateInfos[i].renderPass)->createInfo.ptr()); 636342486a20f07b16f0c5361cdc00fd789b07b1989aMark Lobodzinski pipe_state[i]->pipeline_layout = *getPipelineLayout(dev_data, pCreateInfos[i].layout); 63645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 636542486a20f07b16f0c5361cdc00fd789b07b1989aMark Lobodzinski skip |= PreCallCreateGraphicsPipelines(dev_data, count, pCreateInfos, pipe_state); 63665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6367c70226063be6148056ceeccf835175a1fd59f24fChris Forbes if (skip) { 6368c70226063be6148056ceeccf835175a1fd59f24fChris Forbes for (i = 0; i < count; i++) { 6369c70226063be6148056ceeccf835175a1fd59f24fChris Forbes delete pipe_state[i]; 63701ab616b32d4e5b7d62d4a8c41b0c03ea335ab845Chris Forbes pPipelines[i] = VK_NULL_HANDLE; 6371c70226063be6148056ceeccf835175a1fd59f24fChris Forbes } 63727a456d188475c23b566334be45dc0489b2789653Chris Forbes return VK_ERROR_VALIDATION_FAILED_EXT; 63737a456d188475c23b566334be45dc0489b2789653Chris Forbes } 63747a456d188475c23b566334be45dc0489b2789653Chris Forbes 63757a456d188475c23b566334be45dc0489b2789653Chris Forbes lock.unlock(); 6376bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto result = 6377bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski dev_data->dispatch_table.CreateGraphicsPipelines(device, pipelineCache, count, pCreateInfos, pAllocator, pPipelines); 63787a456d188475c23b566334be45dc0489b2789653Chris Forbes lock.lock(); 63797a456d188475c23b566334be45dc0489b2789653Chris Forbes for (i = 0; i < count; i++) { 638061943a7503bc8594338f3364ef42f1d863486c04Chris Forbes if (pPipelines[i] == VK_NULL_HANDLE) { 638161943a7503bc8594338f3364ef42f1d863486c04Chris Forbes delete pipe_state[i]; 6382bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski } else { 638361943a7503bc8594338f3364ef42f1d863486c04Chris Forbes pipe_state[i]->pipeline = pPipelines[i]; 638461943a7503bc8594338f3364ef42f1d863486c04Chris Forbes dev_data->pipelineMap[pipe_state[i]->pipeline] = pipe_state[i]; 638561943a7503bc8594338f3364ef42f1d863486c04Chris Forbes } 63865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6387c70226063be6148056ceeccf835175a1fd59f24fChris Forbes 63885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 63895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 63905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6391bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count, 6392bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkComputePipelineCreateInfo *pCreateInfos, 6393bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines) { 63940108a1af0b7c6949846e9d71d00bbfb322b6f7caChris Forbes bool skip = false; 63955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 63965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODO : Improve this data struct w/ unique_ptrs so cleanup below is automatic 63974c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis vector<PIPELINE_STATE *> pPipeState(count); 639856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 63995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 64005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t i = 0; 6401b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 64025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (i = 0; i < count; i++) { 64035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODO: Verify compute stage bits 64045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 64055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Create and initialize internal tracking data structure 64064c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis pPipeState[i] = new PIPELINE_STATE; 64074c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis pPipeState[i]->initComputePipeline(&pCreateInfos[i]); 6408c2a5a36d03bbe52f5854a5884346e4a84115e259Tobin Ehlis pPipeState[i]->pipeline_layout = *getPipelineLayout(dev_data, pCreateInfos[i].layout); 64095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 64105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODO: Add Compute Pipeline Verification 6411ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes skip |= !validate_compute_pipeline(dev_data, pPipeState[i]); 64120108a1af0b7c6949846e9d71d00bbfb322b6f7caChris Forbes // skip |= verifyPipelineCreateState(dev_data, pPipeState[i]); 64135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 64145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 64157a456d188475c23b566334be45dc0489b2789653Chris Forbes if (skip) { 64165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (i = 0; i < count; i++) { 64175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Clean up any locally allocated data structures 64184c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis delete pPipeState[i]; 6419fcf67c021fdfcbeb12fb04daa9a69ecd7d376c5cChris Forbes pPipelines[i] = VK_NULL_HANDLE; 64205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 64215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return VK_ERROR_VALIDATION_FAILED_EXT; 64225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 64237a456d188475c23b566334be45dc0489b2789653Chris Forbes 64247a456d188475c23b566334be45dc0489b2789653Chris Forbes lock.unlock(); 6425bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto result = 6426bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski dev_data->dispatch_table.CreateComputePipelines(device, pipelineCache, count, pCreateInfos, pAllocator, pPipelines); 64277a456d188475c23b566334be45dc0489b2789653Chris Forbes lock.lock(); 64287a456d188475c23b566334be45dc0489b2789653Chris Forbes for (i = 0; i < count; i++) { 6429fcf67c021fdfcbeb12fb04daa9a69ecd7d376c5cChris Forbes if (pPipelines[i] == VK_NULL_HANDLE) { 6430fcf67c021fdfcbeb12fb04daa9a69ecd7d376c5cChris Forbes delete pPipeState[i]; 6431bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski } else { 6432fcf67c021fdfcbeb12fb04daa9a69ecd7d376c5cChris Forbes pPipeState[i]->pipeline = pPipelines[i]; 6433fcf67c021fdfcbeb12fb04daa9a69ecd7d376c5cChris Forbes dev_data->pipelineMap[pPipeState[i]->pipeline] = pPipeState[i]; 6434fcf67c021fdfcbeb12fb04daa9a69ecd7d376c5cChris Forbes } 64357a456d188475c23b566334be45dc0489b2789653Chris Forbes } 64367a456d188475c23b566334be45dc0489b2789653Chris Forbes 64375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 64385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 64395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 644089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateSampler(VkDevice device, const VkSamplerCreateInfo *pCreateInfo, 644189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkSampler *pSampler) { 644256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 64434a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateSampler(device, pCreateInfo, pAllocator, pSampler); 64445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 6445b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 6446d31a44af6da568692a73201825459689c9431867Tobin Ehlis dev_data->samplerMap[*pSampler] = unique_ptr<SAMPLER_STATE>(new SAMPLER_STATE(pSampler, pCreateInfo)); 64475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 64485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 64495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 64505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 64510c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlisstatic bool PreCallValidateCreateDescriptorSetLayout(layer_data *dev_data, const VkDescriptorSetLayoutCreateInfo *create_info) { 6452cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.create_descriptor_set_layout) return false; 64530c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis return cvdescriptorset::DescriptorSetLayout::ValidateCreateInfo(dev_data->report_data, create_info); 64540c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis} 64550c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis 64560c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlisstatic void PostCallRecordCreateDescriptorSetLayout(layer_data *dev_data, const VkDescriptorSetLayoutCreateInfo *create_info, 64570c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis VkDescriptorSetLayout set_layout) { 64583f1d2ba6852cf6b1bb4e1f06d690293565108e2cTobin Ehlis // TODO: Convert this to unique_ptr to avoid leaks 64590c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis dev_data->descriptorSetLayoutMap[set_layout] = new cvdescriptorset::DescriptorSetLayout(create_info, set_layout); 64600c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis} 64610c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis 6462bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateDescriptorSetLayout(VkDevice device, const VkDescriptorSetLayoutCreateInfo *pCreateInfo, 6463bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, 6464bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDescriptorSetLayout *pSetLayout) { 646556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 64660c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 64670c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 64680c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis bool skip = PreCallValidateCreateDescriptorSetLayout(dev_data, pCreateInfo); 64690c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis if (!skip) { 64700c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis lock.unlock(); 64710c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis result = dev_data->dispatch_table.CreateDescriptorSetLayout(device, pCreateInfo, pAllocator, pSetLayout); 64720c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis if (VK_SUCCESS == result) { 64730c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis lock.lock(); 64740c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis PostCallRecordCreateDescriptorSetLayout(dev_data, pCreateInfo, *pSetLayout); 64750c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis } 64765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 64775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 64785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 64795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 64809e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz// Used by CreatePipelineLayout and CmdPushConstants. 64819e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz// Note that the index argument is optional and only used by CreatePipelineLayout. 64829e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultzstatic bool validatePushConstantRange(const layer_data *dev_data, const uint32_t offset, const uint32_t size, 64839e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz const char *caller_name, uint32_t index = 0) { 6484cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.push_constant_range) return false; 64859e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz uint32_t const maxPushConstantsSize = dev_data->phys_dev_properties.properties.limits.maxPushConstantsSize; 648683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 64879e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz // Check that offset + size don't exceed the max. 64889e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz // Prevent arithetic overflow here by avoiding addition and testing in this order. 64899e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz if ((offset >= maxPushConstantsSize) || (size > maxPushConstantsSize - offset)) { 64909e24d8153ab63bc3ac08b5a1517c203930b5de91Karl 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. 64919e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz if (0 == strcmp(caller_name, "vkCreatePipelineLayout()")) { 6492e420dd92dcfc04f279e98796a49ee26b2c3ddafeTobin Ehlis if (offset >= maxPushConstantsSize) { 6493e420dd92dcfc04f279e98796a49ee26b2c3ddafeTobin Ehlis skip_call |= 6494df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 6495df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski __LINE__, VALIDATION_ERROR_00877, "DS", 6496cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s call has push constants index %u with offset %u that " 6497cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "exceeds this device's maxPushConstantSize of %u. %s", 6498e420dd92dcfc04f279e98796a49ee26b2c3ddafeTobin Ehlis caller_name, index, offset, maxPushConstantsSize, validation_error_map[VALIDATION_ERROR_00877]); 6499e420dd92dcfc04f279e98796a49ee26b2c3ddafeTobin Ehlis } 6500e420dd92dcfc04f279e98796a49ee26b2c3ddafeTobin Ehlis if (size > maxPushConstantsSize - offset) { 6501e420dd92dcfc04f279e98796a49ee26b2c3ddafeTobin Ehlis skip_call |= 6502df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 6503df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski __LINE__, VALIDATION_ERROR_00880, "DS", 6504cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s call has push constants index %u with offset %u and size %u that " 6505cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "exceeds this device's maxPushConstantSize of %u. %s", 6506e420dd92dcfc04f279e98796a49ee26b2c3ddafeTobin Ehlis caller_name, index, offset, size, maxPushConstantsSize, validation_error_map[VALIDATION_ERROR_00880]); 6507e420dd92dcfc04f279e98796a49ee26b2c3ddafeTobin Ehlis } 65089e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } else if (0 == strcmp(caller_name, "vkCmdPushConstants()")) { 65094527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton if (offset >= maxPushConstantsSize) { 65104527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton skip_call |= 6511df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 6512df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski __LINE__, VALIDATION_ERROR_00991, "DS", 6513cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s call has push constants index %u with offset %u that " 6514cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "exceeds this device's maxPushConstantSize of %u. %s", 65154527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton caller_name, index, offset, maxPushConstantsSize, validation_error_map[VALIDATION_ERROR_00991]); 65164527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton } 65174527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton if (size > maxPushConstantsSize - offset) { 65184527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton skip_call |= 6519df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 6520df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski __LINE__, VALIDATION_ERROR_00992, "DS", 6521cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s call has push constants index %u with offset %u and size %u that " 6522cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "exceeds this device's maxPushConstantSize of %u. %s", 65234527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton caller_name, index, offset, size, maxPushConstantsSize, validation_error_map[VALIDATION_ERROR_00992]); 65244527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton } 65259e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } else { 6526df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 6527df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski __LINE__, DRAWSTATE_INTERNAL_ERROR, "DS", "%s caller not supported.", caller_name); 65289e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 65299e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 65309e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz // size needs to be non-zero and a multiple of 4. 65319e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz if ((size == 0) || ((size & 0x3) != 0)) { 65329e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz if (0 == strcmp(caller_name, "vkCreatePipelineLayout()")) { 6533891f13be101e95697e5af9503f06da38b0c48f79Tobin Ehlis if (size == 0) { 6534df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 6535df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski 0, __LINE__, VALIDATION_ERROR_00878, "DS", 6536cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s call has push constants index %u with " 6537cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "size %u. Size must be greater than zero. %s", 6538891f13be101e95697e5af9503f06da38b0c48f79Tobin Ehlis caller_name, index, size, validation_error_map[VALIDATION_ERROR_00878]); 6539891f13be101e95697e5af9503f06da38b0c48f79Tobin Ehlis } 6540891f13be101e95697e5af9503f06da38b0c48f79Tobin Ehlis if (size & 0x3) { 6541df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 6542df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski 0, __LINE__, VALIDATION_ERROR_00879, "DS", 6543cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s call has push constants index %u with " 6544cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "size %u. Size must be a multiple of 4. %s", 6545891f13be101e95697e5af9503f06da38b0c48f79Tobin Ehlis caller_name, index, size, validation_error_map[VALIDATION_ERROR_00879]); 6546891f13be101e95697e5af9503f06da38b0c48f79Tobin Ehlis } 65479e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } else if (0 == strcmp(caller_name, "vkCmdPushConstants()")) { 65484527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton if (size == 0) { 6549df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 6550df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski 0, __LINE__, VALIDATION_ERROR_01000, "DS", 6551cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s call has push constants index %u with " 6552cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "size %u. Size must be greater than zero. %s", 65534527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton caller_name, index, size, validation_error_map[VALIDATION_ERROR_01000]); 65544527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton } 65554527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton if (size & 0x3) { 6556df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 6557df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski 0, __LINE__, VALIDATION_ERROR_00990, "DS", 6558cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s call has push constants index %u with " 6559cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "size %u. Size must be a multiple of 4. %s", 65604527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton caller_name, index, size, validation_error_map[VALIDATION_ERROR_00990]); 65614527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton } 65629e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } else { 6563df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 6564df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski __LINE__, DRAWSTATE_INTERNAL_ERROR, "DS", "%s caller not supported.", caller_name); 65659e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 65669e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 65679e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz // offset needs to be a multiple of 4. 65689e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz if ((offset & 0x3) != 0) { 65699e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz if (0 == strcmp(caller_name, "vkCreatePipelineLayout()")) { 6570df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 6571df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski __LINE__, VALIDATION_ERROR_02521, "DS", 6572cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s call has push constants index %u with " 6573cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "offset %u. Offset must be a multiple of 4. %s", 65744527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton caller_name, index, offset, validation_error_map[VALIDATION_ERROR_02521]); 65759e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } else if (0 == strcmp(caller_name, "vkCmdPushConstants()")) { 6576df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 6577df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski __LINE__, VALIDATION_ERROR_00989, "DS", 6578cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s call has push constants with " 6579cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "offset %u. Offset must be a multiple of 4. %s", 65804527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton caller_name, offset, validation_error_map[VALIDATION_ERROR_00989]); 65819e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } else { 6582df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 6583df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski __LINE__, DRAWSTATE_INTERNAL_ERROR, "DS", "%s caller not supported.", caller_name); 65849e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 65855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 658683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis return skip_call; 65875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 65885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6589bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo, 659089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout) { 659183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 659256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 6593bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz // TODO : Add checks for VALIDATION_ERRORS 865-870 65949e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz // Push Constant Range checks 659507a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz uint32_t i, j; 65965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (i = 0; i < pCreateInfo->pushConstantRangeCount; ++i) { 659783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= validatePushConstantRange(dev_data, pCreateInfo->pPushConstantRanges[i].offset, 659883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis pCreateInfo->pPushConstantRanges[i].size, "vkCreatePipelineLayout()", i); 65999e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz if (0 == pCreateInfo->pPushConstantRanges[i].stageFlags) { 6600df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 6601df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski __LINE__, VALIDATION_ERROR_00882, "DS", "vkCreatePipelineLayout() call has no stageFlags set. %s", 66024527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton validation_error_map[VALIDATION_ERROR_00882]); 66039e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 66049e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 6605cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip_call) return VK_ERROR_VALIDATION_FAILED_EXT; 660607a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz 6607bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz // As of 1.0.28, there is a VU that states that a stage flag cannot appear more than once in the list of push constant ranges. 660807a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz for (i = 0; i < pCreateInfo->pushConstantRangeCount; ++i) { 660907a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz for (j = i + 1; j < pCreateInfo->pushConstantRangeCount; ++j) { 6610bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz if (0 != (pCreateInfo->pPushConstantRanges[i].stageFlags & pCreateInfo->pPushConstantRanges[j].stageFlags)) { 6611df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 6612df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski 0, __LINE__, VALIDATION_ERROR_00871, "DS", 6613bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz "vkCreatePipelineLayout() Duplicate stage flags found in ranges %d and %d. %s", i, j, 6614bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz validation_error_map[VALIDATION_ERROR_00871]); 66159e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 66165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 66175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6618f73b2046273413ea1338dd714d67c39f8e0fa09eChris Forbes 66194a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout); 66205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 6621b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 66225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis PIPELINE_LAYOUT_NODE &plNode = dev_data->pipelineLayoutMap[*pPipelineLayout]; 662369b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis plNode.layout = *pPipelineLayout; 6624416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis plNode.set_layouts.resize(pCreateInfo->setLayoutCount); 66255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (i = 0; i < pCreateInfo->setLayoutCount; ++i) { 66269a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis plNode.set_layouts[i] = GetDescriptorSetLayout(dev_data, pCreateInfo->pSetLayouts[i]); 66275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6628416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis plNode.push_constant_ranges.resize(pCreateInfo->pushConstantRangeCount); 66295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (i = 0; i < pCreateInfo->pushConstantRangeCount; ++i) { 6630416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis plNode.push_constant_ranges[i] = pCreateInfo->pPushConstantRanges[i]; 66315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 66325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 66335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 66345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 66355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6636bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateDescriptorPool(VkDevice device, const VkDescriptorPoolCreateInfo *pCreateInfo, 6637bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkDescriptorPool *pDescriptorPool) { 663856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 66394a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateDescriptorPool(device, pCreateInfo, pAllocator, pDescriptorPool); 66405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 66415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, 6642414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller (uint64_t)*pDescriptorPool, __LINE__, DRAWSTATE_OUT_OF_MEMORY, "DS", "Created Descriptor Pool 0x%" PRIxLEAST64, 66435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (uint64_t)*pDescriptorPool)) 66445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return VK_ERROR_VALIDATION_FAILED_EXT; 6645a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis DESCRIPTOR_POOL_STATE *pNewNode = new DESCRIPTOR_POOL_STATE(*pDescriptorPool, pCreateInfo); 66465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (NULL == pNewNode) { 66475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, 66485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (uint64_t)*pDescriptorPool, __LINE__, DRAWSTATE_OUT_OF_MEMORY, "DS", 6649a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis "Out of memory while attempting to allocate DESCRIPTOR_POOL_STATE in vkCreateDescriptorPool()")) 66505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return VK_ERROR_VALIDATION_FAILED_EXT; 66515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 6652b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 66535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->descriptorPoolMap[*pDescriptorPool] = pNewNode; 66545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 66555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 66565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Need to do anything if pool create fails? 66575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 66585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 66595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 66605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6661bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL ResetDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, 6662bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDescriptorPoolResetFlags flags) { 66637286e20c06011d3c6fa7edfbdbadd42bb6e8cc35Tobin Ehlis // TODO : Add checks for VALIDATION_ERROR_00928 666456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 66654a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.ResetDescriptorPool(device, descriptorPool, flags); 66665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 6667b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 66685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis clearDescriptorPool(dev_data, device, descriptorPool, flags); 66695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 66705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 66715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 66722c4e180a4442f968b44f3d5136f7ffda706f6428Chris Forbes// Ensure the pool contains enough descriptors and descriptor sets to satisfy 6673789832b514862c7a7b5b847eeb8e7cacb733b77bTobin Ehlis// an allocation request. Fills common_data with the total number of descriptors of each type required, 6674789832b514862c7a7b5b847eeb8e7cacb733b77bTobin Ehlis// as well as DescriptorSetLayout ptrs used for later update. 66757f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlisstatic bool PreCallValidateAllocateDescriptorSets(layer_data *dev_data, const VkDescriptorSetAllocateInfo *pAllocateInfo, 66767f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlis cvdescriptorset::AllocateDescriptorSetsData *common_data) { 66777a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis // Always update common data 66787a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis cvdescriptorset::UpdateAllocateDescriptorSetsData(dev_data, pAllocateInfo, common_data); 6679cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.allocate_descriptor_sets) return false; 66807e73e5c6b3020b96a821985f73012f2af0f1b992Tobin Ehlis // All state checks for AllocateDescriptorSets is done in single function 66817a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis return cvdescriptorset::ValidateAllocateDescriptorSets(dev_data, pAllocateInfo, common_data); 66827e73e5c6b3020b96a821985f73012f2af0f1b992Tobin Ehlis} 66837e73e5c6b3020b96a821985f73012f2af0f1b992Tobin Ehlis// Allocation state was good and call down chain was made so update state based on allocating descriptor sets 66847e73e5c6b3020b96a821985f73012f2af0f1b992Tobin Ehlisstatic void PostCallRecordAllocateDescriptorSets(layer_data *dev_data, const VkDescriptorSetAllocateInfo *pAllocateInfo, 66857f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlis VkDescriptorSet *pDescriptorSets, 66867f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlis const cvdescriptorset::AllocateDescriptorSetsData *common_data) { 66877e73e5c6b3020b96a821985f73012f2af0f1b992Tobin Ehlis // All the updates are contained in a single cvdescriptorset function 66882c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis cvdescriptorset::PerformAllocateDescriptorSets(pAllocateInfo, pDescriptorSets, common_data, &dev_data->descriptorPoolMap, 6689b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis &dev_data->setMap, dev_data); 66902c4e180a4442f968b44f3d5136f7ffda706f6428Chris Forbes} 66912c4e180a4442f968b44f3d5136f7ffda706f6428Chris Forbes 6692bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL AllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo *pAllocateInfo, 6693bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDescriptorSet *pDescriptorSets) { 669456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 6695b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 66967f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlis cvdescriptorset::AllocateDescriptorSetsData common_data(pAllocateInfo->descriptorSetCount); 66977f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlis bool skip_call = PreCallValidateAllocateDescriptorSets(dev_data, pAllocateInfo, &common_data); 6698b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 6699d173e0daab123373ce75105f2a908f6ae7cef6abChris Forbes 6700cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip_call) return VK_ERROR_VALIDATION_FAILED_EXT; 6701d173e0daab123373ce75105f2a908f6ae7cef6abChris Forbes 67024a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.AllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets); 67036511ce241f7f210211e0c0e882f3c14889071f4dChris Forbes 67045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 6705b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.lock(); 67067f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlis PostCallRecordAllocateDescriptorSets(dev_data, pAllocateInfo, pDescriptorSets, &common_data); 6707b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 67085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 67095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 67105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 6711cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis// Verify state before freeing DescriptorSets 6712cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlisstatic bool PreCallValidateFreeDescriptorSets(const layer_data *dev_data, VkDescriptorPool pool, uint32_t count, 6713cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis const VkDescriptorSet *descriptor_sets) { 6714cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.free_descriptor_sets) return false; 6715cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis bool skip_call = false; 6716cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis // First make sure sets being destroyed are not currently in-use 6717405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour for (uint32_t i = 0; i < count; ++i) { 6718405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (descriptor_sets[i] != VK_NULL_HANDLE) { 6719405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour skip_call |= validateIdleDescriptorSet(dev_data, descriptor_sets[i], "vkFreeDescriptorSets"); 6720405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 6721405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 6722cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis 67239a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DESCRIPTOR_POOL_STATE *pool_state = GetDescriptorPoolState(dev_data, pool); 6724a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis if (pool_state && !(VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT & pool_state->createInfo.flags)) { 6725cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis // Can't Free from a NON_FREE pool 6726cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, 67271c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis reinterpret_cast<uint64_t &>(pool), __LINE__, VALIDATION_ERROR_00922, "DS", 6728cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis "It is invalid to call vkFreeDescriptorSets() with a pool created without setting " 67291c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis "VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT. %s", 67301c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis validation_error_map[VALIDATION_ERROR_00922]); 6731cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis } 6732cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis return skip_call; 6733cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis} 6734cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis// Sets have been removed from the pool so update underlying state 6735cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlisstatic void PostCallRecordFreeDescriptorSets(layer_data *dev_data, VkDescriptorPool pool, uint32_t count, 6736cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis const VkDescriptorSet *descriptor_sets) { 67379a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DESCRIPTOR_POOL_STATE *pool_state = GetDescriptorPoolState(dev_data, pool); 6738cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis // Update available descriptor sets in pool 6739cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis pool_state->availableSets += count; 6740cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis 6741cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis // For each freed descriptor add its resources back into the pool as available and remove from pool and setMap 6742cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis for (uint32_t i = 0; i < count; ++i) { 6743405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (descriptor_sets[i] != VK_NULL_HANDLE) { 6744405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour auto descriptor_set = dev_data->setMap[descriptor_sets[i]]; 6745405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour uint32_t type_index = 0, descriptor_count = 0; 6746405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour for (uint32_t j = 0; j < descriptor_set->GetBindingCount(); ++j) { 6747405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour type_index = static_cast<uint32_t>(descriptor_set->GetTypeFromIndex(j)); 6748405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour descriptor_count = descriptor_set->GetDescriptorCountFromIndex(j); 6749405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour pool_state->availableDescriptorTypeCount[type_index] += descriptor_count; 6750405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 6751405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour freeDescriptorSet(dev_data, descriptor_set); 6752405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour pool_state->sets.erase(descriptor_set); 6753405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 6754cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis } 6755cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis} 67565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6757bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL FreeDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool, uint32_t count, 6758bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkDescriptorSet *pDescriptorSets) { 675956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 67605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Make sure that no sets being destroyed are in-flight 6761b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 676283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = PreCallValidateFreeDescriptorSets(dev_data, descriptorPool, count, pDescriptorSets); 6763b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 6764e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis 6765cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip_call) return VK_ERROR_VALIDATION_FAILED_EXT; 67664a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.FreeDescriptorSets(device, descriptorPool, count, pDescriptorSets); 67675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 6768b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.lock(); 6769cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis PostCallRecordFreeDescriptorSets(dev_data, descriptorPool, count, pDescriptorSets); 6770b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 67715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 67725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 67735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 67746b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis// TODO : This is a Proof-of-concept for core validation architecture 67756b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis// Really we'll want to break out these functions to separate files but 67766b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis// keeping it all together here to prove out design 67776b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis// PreCallValidate* handles validating all of the state prior to calling down chain to UpdateDescriptorSets() 67786b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlisstatic bool PreCallValidateUpdateDescriptorSets(layer_data *dev_data, uint32_t descriptorWriteCount, 67796b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis const VkWriteDescriptorSet *pDescriptorWrites, uint32_t descriptorCopyCount, 67806b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis const VkCopyDescriptorSet *pDescriptorCopies) { 6781cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.update_descriptor_sets) return false; 67826b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis // First thing to do is perform map look-ups. 67836b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis // NOTE : UpdateDescriptorSets is somewhat unique in that it's operating on a number of DescriptorSets 67846b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis // so we can't just do a single map look-up up-front, but do them individually in functions below 67856b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis 67866b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis // Now make call(s) that validate state, but don't perform state updates in this function 67876b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis // Note, here DescriptorSets is unique in that we don't yet have an instance. Using a helper function in the 67886b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis // namespace which will parse params and make calls into specific class instances 6789104ab082916e41467ef60baaab7a5a8b2e02c59cTobin Ehlis return cvdescriptorset::ValidateUpdateDescriptorSets(dev_data->report_data, dev_data, descriptorWriteCount, pDescriptorWrites, 6790104ab082916e41467ef60baaab7a5a8b2e02c59cTobin Ehlis descriptorCopyCount, pDescriptorCopies); 67916b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis} 67926b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis// PostCallRecord* handles recording state updates following call down chain to UpdateDescriptorSets() 67936b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlisstatic void PostCallRecordUpdateDescriptorSets(layer_data *dev_data, uint32_t descriptorWriteCount, 67946b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis const VkWriteDescriptorSet *pDescriptorWrites, uint32_t descriptorCopyCount, 67956b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis const VkCopyDescriptorSet *pDescriptorCopies) { 6796104ab082916e41467ef60baaab7a5a8b2e02c59cTobin Ehlis cvdescriptorset::PerformUpdateDescriptorSets(dev_data, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, 67976b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis pDescriptorCopies); 67986b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis} 67995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6800bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL UpdateDescriptorSets(VkDevice device, uint32_t descriptorWriteCount, 6801bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkWriteDescriptorSet *pDescriptorWrites, uint32_t descriptorCopyCount, 6802bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkCopyDescriptorSet *pDescriptorCopies) { 68036b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis // Only map look-up at top level is for device-level layer_data 680456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 6805b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 68066b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis bool skip_call = PreCallValidateUpdateDescriptorSets(dev_data, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, 68076b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis pDescriptorCopies); 6808b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 68096b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis if (!skip_call) { 68104a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.UpdateDescriptorSets(device, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, 68114a0754042cf090e131e9e769d8a3633c228625beChris Forbes pDescriptorCopies); 68126b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis lock.lock(); 68136b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis // Since UpdateDescriptorSets() is void, nothing to check prior to updating state 68146b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis PostCallRecordUpdateDescriptorSets(dev_data, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, 68156b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis pDescriptorCopies); 68165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 68175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 68185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6819bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL AllocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo *pCreateInfo, 6820bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkCommandBuffer *pCommandBuffer) { 682156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 68224a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.AllocateCommandBuffers(device, pCreateInfo, pCommandBuffer); 68235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 6824b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 68259a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pPool = GetCommandPoolNode(dev_data, pCreateInfo->commandPool); 6826cd9a648074f67a1d44c15a056b90fc66da8ead17Chris Forbes 6827cd9a648074f67a1d44c15a056b90fc66da8ead17Chris Forbes if (pPool) { 682872d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis for (uint32_t i = 0; i < pCreateInfo->commandBufferCount; i++) { 68295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Add command buffer to its commandPool map 6830cd9a648074f67a1d44c15a056b90fc66da8ead17Chris Forbes pPool->commandBuffers.push_back(pCommandBuffer[i]); 68315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis GLOBAL_CB_NODE *pCB = new GLOBAL_CB_NODE; 68325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Add command buffer to map 68335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->commandBufferMap[pCommandBuffer[i]] = pCB; 68345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis resetCB(dev_data, pCommandBuffer[i]); 68355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->createInfo = *pCreateInfo; 68365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->device = device; 68375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 68385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6839b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 68405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 68415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 68425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 68435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6844883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis// Add bindings between the given cmd buffer & framebuffer and the framebuffer's children 6845c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlisstatic void AddFramebufferBinding(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, FRAMEBUFFER_STATE *fb_state) { 68460245b74a083d2cb3b083571deb0fe13b4ab428a4Tobin Ehlis addCommandBufferBinding(&fb_state->cb_bindings, 68470245b74a083d2cb3b083571deb0fe13b4ab428a4Tobin Ehlis {reinterpret_cast<uint64_t &>(fb_state->framebuffer), VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT}, 68480245b74a083d2cb3b083571deb0fe13b4ab428a4Tobin Ehlis cb_state); 6849883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis for (auto attachment : fb_state->attachments) { 6850883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis auto view_state = attachment.view_state; 6851883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis if (view_state) { 685203ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis AddCommandBufferBindingImageView(dev_data, cb_state, view_state); 6853883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis } 68549a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto rp_state = GetRenderPassState(dev_data, fb_state->createInfo.renderPass); 6855883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis if (rp_state) { 6856883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis addCommandBufferBinding( 6857883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis &rp_state->cb_bindings, 6858883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis {reinterpret_cast<uint64_t &>(rp_state->renderPass), VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT}, cb_state); 6859883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis } 6860883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis } 6861883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis} 6862883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis 6863bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL BeginCommandBuffer(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo *pBeginInfo) { 686483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 686556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 6866b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 68675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Validate command buffer level 68689a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *cb_node = GetCBNode(dev_data, commandBuffer); 6869f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis if (cb_node) { 68705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // This implicitly resets the Cmd Buffer so make sure any fence is done and then clear memory references 6871a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis if (dev_data->globalInFlightCmdBuffers.count(commandBuffer)) { 687283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= 6873a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 68744527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton (uint64_t)commandBuffer, __LINE__, VALIDATION_ERROR_00104, "MEM", 6875d79335137b414d5f89284a9ab3e014beb4ada3ebMike Weiblen "Calling vkBeginCommandBuffer() on active command buffer 0x%p before it has completed. " 68764527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton "You must check command buffer fence before this call. %s", 68774527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton commandBuffer, validation_error_map[VALIDATION_ERROR_00104]); 68785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6879f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis clear_cmd_buf_and_mem_references(dev_data, cb_node); 6880f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis if (cb_node->createInfo.level != VK_COMMAND_BUFFER_LEVEL_PRIMARY) { 68815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Secondary Command Buffer 68825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkCommandBufferInheritanceInfo *pInfo = pBeginInfo->pInheritanceInfo; 68835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!pInfo) { 688483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= 68855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 68864527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton reinterpret_cast<uint64_t>(commandBuffer), __LINE__, VALIDATION_ERROR_00106, "DS", 6887bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "vkBeginCommandBuffer(): Secondary Command Buffer (0x%p) must have inheritance info. %s", commandBuffer, 6888bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski validation_error_map[VALIDATION_ERROR_00106]); 68895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 68905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pBeginInfo->flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT) { 68912c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis // Object_tracker makes sure these objects are valid 68922c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis assert(pInfo->renderPass); 68932c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis assert(pInfo->framebuffer); 68942c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis string errorString = ""; 68959a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto framebuffer = GetFramebufferState(dev_data, pInfo->framebuffer); 68962c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis if (framebuffer) { 68972c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis if ((framebuffer->createInfo.renderPass != pInfo->renderPass) && 68982c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis !verify_renderpass_compatibility(dev_data, framebuffer->renderPassCreateInfo.ptr(), 68999a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GetRenderPassState(dev_data, pInfo->renderPass)->createInfo.ptr(), 69002c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis errorString)) { 69012c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis // renderPass that framebuffer was created with must be compatible with local renderPass 69022c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 69032c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 69042c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis reinterpret_cast<uint64_t>(commandBuffer), __LINE__, VALIDATION_ERROR_00112, "DS", 69052c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis "vkBeginCommandBuffer(): Secondary Command " 6906cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Buffer (0x%p) renderPass (0x%" PRIxLEAST64 6907cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ") is incompatible w/ framebuffer " 69082c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis "(0x%" PRIxLEAST64 ") w/ render pass (0x%" PRIxLEAST64 ") due to: %s. %s", 69092c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis commandBuffer, reinterpret_cast<const uint64_t &>(pInfo->renderPass), 69102c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis reinterpret_cast<const uint64_t &>(pInfo->framebuffer), 69112c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis reinterpret_cast<uint64_t &>(framebuffer->createInfo.renderPass), 69122c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis errorString.c_str(), validation_error_map[VALIDATION_ERROR_00112]); 69135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 69142c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis // Connect this framebuffer and its children to this cmdBuffer 69152c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis AddFramebufferBinding(dev_data, cb_node, framebuffer); 69165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 69175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 69184527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton if ((pInfo->occlusionQueryEnable == VK_FALSE || dev_data->enabled_features.occlusionQueryPrecise == VK_FALSE) && 69195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (pInfo->queryFlags & VK_QUERY_CONTROL_PRECISE_BIT)) { 692083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 692183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t>(commandBuffer), 69224527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton __LINE__, VALIDATION_ERROR_00107, "DS", 692383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis "vkBeginCommandBuffer(): Secondary Command Buffer (0x%p) must not have " 692483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis "VK_QUERY_CONTROL_PRECISE_BIT if occulusionQuery is disabled or the device does not " 69254527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton "support precise occlusion queries. %s", 69264527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton commandBuffer, validation_error_map[VALIDATION_ERROR_00107]); 69275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 69285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 69295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pInfo && pInfo->renderPass != VK_NULL_HANDLE) { 69309a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto renderPass = GetRenderPassState(dev_data, pInfo->renderPass); 693116387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes if (renderPass) { 6932fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes if (pInfo->subpass >= renderPass->createInfo.subpassCount) { 693383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg( 6934bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 6935bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski (uint64_t)commandBuffer, __LINE__, VALIDATION_ERROR_00111, "DS", 69364527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton "vkBeginCommandBuffer(): Secondary Command Buffers (0x%p) must have a subpass index (%d) " 69374527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton "that is less than the number of subpasses (%d). %s", 69384527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton commandBuffer, pInfo->subpass, renderPass->createInfo.subpassCount, 69394527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton validation_error_map[VALIDATION_ERROR_00111]); 69405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 69415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 69425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 69435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6944f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis if (CB_RECORDING == cb_node->state) { 6945cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski skip_call |= 6946cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 6947cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski (uint64_t)commandBuffer, __LINE__, VALIDATION_ERROR_00103, "DS", 6948cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkBeginCommandBuffer(): Cannot call Begin on command buffer (0x%p" 6949cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ") in the RECORDING state. Must first call vkEndCommandBuffer(). %s", 6950cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski commandBuffer, validation_error_map[VALIDATION_ERROR_00103]); 6951347d4d3139a1e743ed85bd375c20fd35bbe68d74Chris Forbes } else if (CB_RECORDED == cb_node->state || (CB_INVALID == cb_node->state && CMD_END == cb_node->last_cmd)) { 6952f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis VkCommandPool cmdPool = cb_node->createInfo.commandPool; 69539a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pPool = GetCommandPoolNode(dev_data, cmdPool); 6954cd9a648074f67a1d44c15a056b90fc66da8ead17Chris Forbes if (!(VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT & pPool->createFlags)) { 695583b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= 69565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 69574527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton (uint64_t)commandBuffer, __LINE__, VALIDATION_ERROR_00105, "DS", 6958226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "Call to vkBeginCommandBuffer() on command buffer (0x%p" 6959414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller ") attempts to implicitly reset cmdBuffer created from command pool (0x%" PRIxLEAST64 69604527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton ") that does NOT have the VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT bit set. %s", 69614527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton commandBuffer, (uint64_t)cmdPool, validation_error_map[VALIDATION_ERROR_00105]); 69625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 69635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis resetCB(dev_data, commandBuffer); 69645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 69655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Set updated state here in case implicit reset occurs above 6966f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->state = CB_RECORDING; 6967f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->beginInfo = *pBeginInfo; 6968f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis if (cb_node->beginInfo.pInheritanceInfo) { 6969f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->inheritanceInfo = *(cb_node->beginInfo.pInheritanceInfo); 6970f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->beginInfo.pInheritanceInfo = &cb_node->inheritanceInfo; 6971888e1d268098177fde4a2263e3d7b7cc415f1debMark Young // If we are a secondary command-buffer and inheriting. Update the items we should inherit. 6972f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis if ((cb_node->createInfo.level != VK_COMMAND_BUFFER_LEVEL_PRIMARY) && 6973f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis (cb_node->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT)) { 69749a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis cb_node->activeRenderPass = GetRenderPassState(dev_data, cb_node->beginInfo.pInheritanceInfo->renderPass); 6975f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->activeSubpass = cb_node->beginInfo.pInheritanceInfo->subpass; 6976350841afb70bf8dcfc3c6ec6b66f0aaa639553a3Tobin Ehlis cb_node->activeFramebuffer = cb_node->beginInfo.pInheritanceInfo->framebuffer; 6977f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->framebuffers.insert(cb_node->beginInfo.pInheritanceInfo->framebuffer); 6978888e1d268098177fde4a2263e3d7b7cc415f1debMark Young } 69795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 69805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6981b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 698283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis if (skip_call) { 69835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return VK_ERROR_VALIDATION_FAILED_EXT; 69845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 69854a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.BeginCommandBuffer(commandBuffer, pBeginInfo); 6986400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis 69875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 69885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 69895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 699089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL EndCommandBuffer(VkCommandBuffer commandBuffer) { 699183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 69925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkResult result = VK_SUCCESS; 699356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 6994b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 69959a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 69965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 69974527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton if ((VK_COMMAND_BUFFER_LEVEL_PRIMARY == pCB->createInfo.level) || 69984527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton !(pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT)) { 6999fd61966f8d41b5bce15620b70563b7864cbb28feCody Northrop // This needs spec clarification to update valid usage, see comments in PR: 7000fd61966f8d41b5bce15620b70563b7864cbb28feCody Northrop // https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/pull/516#discussion_r63013756 7001ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen skip_call |= insideRenderPass(dev_data, pCB, "vkEndCommandBuffer()", VALIDATION_ERROR_00123); 7002fd61966f8d41b5bce15620b70563b7864cbb28feCody Northrop } 700329f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_END, "vkEndCommandBuffer()"); 70041ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_END); 70055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto query : pCB->activeQueries) { 7006df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= 7007df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 7008df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(commandBuffer), __LINE__, VALIDATION_ERROR_00124, "DS", 7009df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "Ending command buffer with in progress query: queryPool 0x%" PRIx64 ", index %d. %s", 7010df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski (uint64_t)(query.pool), query.index, validation_error_map[VALIDATION_ERROR_00124]); 70115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 70125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 701383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis if (!skip_call) { 7014b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 70154a0754042cf090e131e9e769d8a3633c228625beChris Forbes result = dev_data->dispatch_table.EndCommandBuffer(commandBuffer); 7016b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.lock(); 70175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 70185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->state = CB_RECORDED; 70195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Reset CB status flags 70205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->status = 0; 70215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 70225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 70235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis result = VK_ERROR_VALIDATION_FAILED_EXT; 70245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7025b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 70265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 70275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 70285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7029bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL ResetCommandBuffer(VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags) { 7030bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis bool skip_call = false; 703156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7032b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 70339a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 70345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkCommandPool cmdPool = pCB->createInfo.commandPool; 70359a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pPool = GetCommandPoolNode(dev_data, cmdPool); 7036cd9a648074f67a1d44c15a056b90fc66da8ead17Chris Forbes if (!(VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT & pPool->createFlags)) { 7037bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 70384527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton (uint64_t)commandBuffer, __LINE__, VALIDATION_ERROR_00093, "DS", 7039226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "Attempt to reset command buffer (0x%p) created from command pool (0x%" PRIxLEAST64 70404527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton ") that does NOT have the VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT bit set. %s", 70414527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton commandBuffer, (uint64_t)cmdPool, validation_error_map[VALIDATION_ERROR_00093]); 70425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7043cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlis skip_call |= checkCommandBufferInFlight(dev_data, pCB, "reset", VALIDATION_ERROR_00092); 7044b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7045cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip_call) return VK_ERROR_VALIDATION_FAILED_EXT; 70464a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.ResetCommandBuffer(commandBuffer, flags); 70475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 7048b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.lock(); 7049a964cad279f9749cd9ebfc7555247ff3bff26d53Chris Forbes dev_data->globalInFlightCmdBuffers.erase(commandBuffer); 70505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis resetCB(dev_data, commandBuffer); 7051b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 70525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 70535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 70545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 705593c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski 7056bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBindPipeline(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, 7057bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkPipeline pipeline) { 7058e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis bool skip = false; 705956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7060b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 70619a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer); 7062e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis if (cb_state) { 7063baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip |= ValidateCmdQueueFlags(dev_data, cb_state, "vkCmdBindPipeline()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, 7064baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt VALIDATION_ERROR_00603); 706529f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip |= ValidateCmd(dev_data, cb_state, CMD_BINDPIPELINE, "vkCmdBindPipeline()"); 70661ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(cb_state, CMD_BINDPIPELINE); 7067e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis if ((VK_PIPELINE_BIND_POINT_COMPUTE == pipelineBindPoint) && (cb_state->activeRenderPass)) { 7068e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis skip |= 70695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 70705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (uint64_t)pipeline, __LINE__, DRAWSTATE_INVALID_RENDERPASS_CMD, "DS", 7071414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller "Incorrectly binding compute pipeline (0x%" PRIxLEAST64 ") during active RenderPass (0x%" PRIxLEAST64 ")", 7072e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis (uint64_t)pipeline, (uint64_t)cb_state->activeRenderPass->renderPass); 70735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 70744527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton // TODO: VALIDATION_ERROR_00594 VALIDATION_ERROR_00596 70755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7076e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis PIPELINE_STATE *pipe_state = getPipelineState(dev_data, pipeline); 7077e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis if (pipe_state) { 7078e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis cb_state->lastBound[pipelineBindPoint].pipeline_state = pipe_state; 7079e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis set_cb_pso_status(cb_state, pipe_state); 7080e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis set_pipeline_state(pipe_state); 7081daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski skip |= validate_dual_src_blend_feature(dev_data, pipe_state); 70825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 7083e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 70844527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton (uint64_t)pipeline, __LINE__, VALIDATION_ERROR_00600, "DS", 70854527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton "Attempt to bind Pipeline 0x%" PRIxLEAST64 " that doesn't exist! %s", (uint64_t)(pipeline), 70864527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton validation_error_map[VALIDATION_ERROR_00600]); 7087e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis } 7088e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis addCommandBufferBinding(&pipe_state->cb_bindings, 7089e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis {reinterpret_cast<uint64_t &>(pipeline), VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT}, cb_state); 7090e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis if (VK_PIPELINE_BIND_POINT_GRAPHICS == pipelineBindPoint) { 7091e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis // Add binding for child renderpass 70929a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto rp_state = GetRenderPassState(dev_data, pipe_state->graphicsPipelineCI.renderPass); 7093e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis if (rp_state) { 7094e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis addCommandBufferBinding( 7095e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis &rp_state->cb_bindings, 7096e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis {reinterpret_cast<uint64_t &>(rp_state->renderPass), VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT}, cb_state); 7097e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis } 70985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 70995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7100b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7101cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdBindPipeline(commandBuffer, pipelineBindPoint, pipeline); 71025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 71035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7104bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetViewport(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, 7105bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkViewport *pViewports) { 710683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 710756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7108b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 71099a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 71105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 7111baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip_call |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetViewport()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_01446); 711229f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_SETVIEWPORTSTATE, "vkCmdSetViewport()"); 71131ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETVIEWPORTSTATE); 7114bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pCB->viewportMask |= ((1u << viewportCount) - 1u) << firstViewport; 71155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7116b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7117cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.CmdSetViewport(commandBuffer, firstViewport, viewportCount, pViewports); 71185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 71195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7120bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetScissor(VkCommandBuffer commandBuffer, uint32_t firstScissor, uint32_t scissorCount, 7121bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkRect2D *pScissors) { 712283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 712356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7124b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 71259a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 71265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 7127baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip_call |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetScissor()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_01495); 712829f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_SETSCISSORSTATE, "vkCmdSetScissor()"); 71291ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETSCISSORSTATE); 7130bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pCB->scissorMask |= ((1u << scissorCount) - 1u) << firstScissor; 71315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7132b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7133cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.CmdSetScissor(commandBuffer, firstScissor, scissorCount, pScissors); 71345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 71355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 713689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdSetLineWidth(VkCommandBuffer commandBuffer, float lineWidth) { 7137a27508babf63d50aea75883a3702979193c23683Mark Young 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) { 7142baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip_call |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetLineWidth()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_01480); 714329f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_SETLINEWIDTHSTATE, "vkCmdSetLineWidth()"); 71441ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETLINEWIDTHSTATE); 71455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->status |= CBSTATUS_LINE_WIDTH_SET; 7146a27508babf63d50aea75883a3702979193c23683Mark Young 71474c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis PIPELINE_STATE *pPipeTrav = pCB->lastBound[VK_PIPELINE_BIND_POINT_GRAPHICS].pipeline_state; 7148a27508babf63d50aea75883a3702979193c23683Mark Young if (pPipeTrav != NULL && !isDynamic(pPipeTrav, VK_DYNAMIC_STATE_LINE_WIDTH)) { 7149df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= 7150df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 7151df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(commandBuffer), __LINE__, VALIDATION_ERROR_01476, "DS", 7152df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "vkCmdSetLineWidth called but pipeline was created without VK_DYNAMIC_STATE_LINE_WIDTH " 7153df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "flag. This is undefined behavior and could be ignored. %s", 7154df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski validation_error_map[VALIDATION_ERROR_01476]); 7155a27508babf63d50aea75883a3702979193c23683Mark Young } else { 7156df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= verifyLineWidth(dev_data, DRAWSTATE_INVALID_SET, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 7157df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t &>(commandBuffer), lineWidth); 7158a27508babf63d50aea75883a3702979193c23683Mark Young } 71595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7160b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7161cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.CmdSetLineWidth(commandBuffer, lineWidth); 71625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 71635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7164bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetDepthBias(VkCommandBuffer commandBuffer, float depthBiasConstantFactor, float depthBiasClamp, 7165bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski float depthBiasSlopeFactor) { 716683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 716756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7168b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 71699a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 71705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 7171baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip_call |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetDepthBias()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_01485); 717229f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_SETDEPTHBIASSTATE, "vkCmdSetDepthBias()"); 7173434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski if ((depthBiasClamp != 0.0) && (!dev_data->enabled_features.depthBiasClamp)) { 7174df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= 7175df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 7176df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(commandBuffer), __LINE__, VALIDATION_ERROR_01482, "DS", 7177df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "vkCmdSetDepthBias(): the depthBiasClamp device feature is disabled: the depthBiasClamp " 7178df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "parameter must be set to 0.0. %s", 7179df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski validation_error_map[VALIDATION_ERROR_01482]); 7180434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski } 7181434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski if (!skip_call) { 7182434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski UpdateCmdBufferLastCmd(pCB, CMD_SETDEPTHBIASSTATE); 7183434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski pCB->status |= CBSTATUS_DEPTH_BIAS_SET; 7184434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski } 71855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7186b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 718783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis if (!skip_call) 71884a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdSetDepthBias(commandBuffer, depthBiasConstantFactor, depthBiasClamp, depthBiasSlopeFactor); 71895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 71905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 719189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdSetBlendConstants(VkCommandBuffer commandBuffer, const float blendConstants[4]) { 719283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 719356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7194b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 71959a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 71965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 7197baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip_call |= 7198baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetBlendConstants()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_01553); 719929f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_SETBLENDSTATE, "vkCmdSetBlendConstants()"); 72001ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETBLENDSTATE); 72013d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis pCB->status |= CBSTATUS_BLEND_CONSTANTS_SET; 72025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7203b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7204cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.CmdSetBlendConstants(commandBuffer, blendConstants); 72055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 72065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7207bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetDepthBounds(VkCommandBuffer commandBuffer, float minDepthBounds, float maxDepthBounds) { 720883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 720956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7210b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 72119a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 72125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 7213baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip_call |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetDepthBounds()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_01509); 721429f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_SETDEPTHBOUNDSSTATE, "vkCmdSetDepthBounds()"); 72151ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETDEPTHBOUNDSSTATE); 72165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->status |= CBSTATUS_DEPTH_BOUNDS_SET; 72175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7218b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7219cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.CmdSetDepthBounds(commandBuffer, minDepthBounds, maxDepthBounds); 72205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 72215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7222bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetStencilCompareMask(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, 7223bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski uint32_t compareMask) { 722483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 722556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7226b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 72279a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 72285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 7229baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip_call |= 7230baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetStencilCompareMask()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_01519); 723129f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_SETSTENCILREADMASKSTATE, "vkCmdSetStencilCompareMask()"); 72321ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETSTENCILREADMASKSTATE); 72335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->status |= CBSTATUS_STENCIL_READ_MASK_SET; 72345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7235b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7236cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.CmdSetStencilCompareMask(commandBuffer, faceMask, compareMask); 72375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 72385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7239bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetStencilWriteMask(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t writeMask) { 724083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 724156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7242b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 72439a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 72445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 7245baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip_call |= 7246baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetStencilWriteMask()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_01525); 724729f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_SETSTENCILWRITEMASKSTATE, "vkCmdSetStencilWriteMask()"); 72481ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETSTENCILWRITEMASKSTATE); 72495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->status |= CBSTATUS_STENCIL_WRITE_MASK_SET; 72505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7251b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7252cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.CmdSetStencilWriteMask(commandBuffer, faceMask, writeMask); 72535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 72545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7255bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetStencilReference(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t reference) { 725683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 725756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7258b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 72599a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 72605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 7261baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip_call |= 7262baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetStencilReference()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_01531); 726329f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_SETSTENCILREFERENCESTATE, "vkCmdSetStencilReference()"); 72641ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETSTENCILREFERENCESTATE); 72655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->status |= CBSTATUS_STENCIL_REFERENCE_SET; 72665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7267b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7268cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.CmdSetStencilReference(commandBuffer, faceMask, reference); 72695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 72705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7271bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBindDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, 7272bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkPipelineLayout layout, uint32_t firstSet, uint32_t setCount, 7273bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkDescriptorSet *pDescriptorSets, uint32_t dynamicOffsetCount, 7274bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const uint32_t *pDynamicOffsets) { 7275946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski bool skip = false; 727656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7277b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7278946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer); 7279946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (cb_state) { 7280baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip |= ValidateCmdQueueFlags(dev_data, cb_state, "vkCmdBindDescriptorSets()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, 7281baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt VALIDATION_ERROR_00985); 7282946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ValidateCmd(dev_data, cb_state, CMD_BINDDESCRIPTORSETS, "vkCmdBindDescriptorSets()"); 7283ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski // Track total count of dynamic descriptor types to make sure we have an offset for each one 7284946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski uint32_t total_dynamic_descriptors = 0; 7285946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski string error_string = ""; 7286946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski uint32_t last_set_index = firstSet + setCount - 1; 7287946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (last_set_index >= cb_state->lastBound[pipelineBindPoint].boundDescriptorSets.size()) { 7288946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->lastBound[pipelineBindPoint].boundDescriptorSets.resize(last_set_index + 1); 7289946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->lastBound[pipelineBindPoint].dynamicOffsets.resize(last_set_index + 1); 7290946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski } 7291946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski auto old_final_bound_set = cb_state->lastBound[pipelineBindPoint].boundDescriptorSets[last_set_index]; 7292ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski auto pipeline_layout = getPipelineLayout(dev_data, layout); 7293ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski for (uint32_t set_idx = 0; set_idx < setCount; set_idx++) { 7294ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski cvdescriptorset::DescriptorSet *descriptor_set = GetSetNode(dev_data, pDescriptorSets[set_idx]); 7295ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski if (descriptor_set) { 7296946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->lastBound[pipelineBindPoint].pipeline_layout = *pipeline_layout; 7297946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->lastBound[pipelineBindPoint].boundDescriptorSets[set_idx + firstSet] = descriptor_set; 7298946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 7299946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t)pDescriptorSets[set_idx], __LINE__, 7300946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski DRAWSTATE_NONE, "DS", "Descriptor Set 0x%" PRIxLEAST64 " bound on pipeline %s", 7301946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski (uint64_t)pDescriptorSets[set_idx], string_VkPipelineBindPoint(pipelineBindPoint)); 7302ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski if (!descriptor_set->IsUpdated() && (descriptor_set->GetTotalDescriptorCount() != 0)) { 7303946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, 7304946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t)pDescriptorSets[set_idx], __LINE__, 7305946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski DRAWSTATE_DESCRIPTOR_SET_NOT_UPDATED, "DS", 7306946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "Descriptor Set 0x%" PRIxLEAST64 7307946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski " bound but it was never updated. You may want to either update it or not bind it.", 7308946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski (uint64_t)pDescriptorSets[set_idx]); 7309ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } 7310ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski // Verify that set being bound is compatible with overlapping setLayout of pipelineLayout 7311946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (!verify_set_layout_compatibility(dev_data, descriptor_set, pipeline_layout, set_idx + firstSet, error_string)) { 7312946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 7313946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t)pDescriptorSets[set_idx], __LINE__, 7314946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski VALIDATION_ERROR_00974, "DS", 7315946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "descriptorSet #%u being bound is not compatible with overlapping descriptorSetLayout " 7316946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "at index %u of pipelineLayout 0x%" PRIxLEAST64 " due to: %s. %s", 7317946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski set_idx, set_idx + firstSet, reinterpret_cast<uint64_t &>(layout), error_string.c_str(), 7318946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski validation_error_map[VALIDATION_ERROR_00974]); 73195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7320ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski 7321946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski auto set_dynamic_descriptor_count = descriptor_set->GetDynamicDescriptorCount(); 7322ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski 7323946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->lastBound[pipelineBindPoint].dynamicOffsets[firstSet + set_idx].clear(); 7324ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski 7325946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (set_dynamic_descriptor_count) { 7326ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski // First make sure we won't overstep bounds of pDynamicOffsets array 7327946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if ((total_dynamic_descriptors + set_dynamic_descriptor_count) > dynamicOffsetCount) { 7328946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 7329946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t)pDescriptorSets[set_idx], 7330946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski __LINE__, DRAWSTATE_INVALID_DYNAMIC_OFFSET_COUNT, "DS", 7331946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "descriptorSet #%u (0x%" PRIxLEAST64 7332946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski ") requires %u dynamicOffsets, but only %u dynamicOffsets are left in pDynamicOffsets " 7333946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "array. There must be one dynamic offset for each dynamic descriptor being bound.", 7334946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski set_idx, (uint64_t)pDescriptorSets[set_idx], descriptor_set->GetDynamicDescriptorCount(), 7335946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski (dynamicOffsetCount - total_dynamic_descriptors)); 7336ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } else { // Validate and store dynamic offsets with the set 7337ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski // Validate Dynamic Offset Minimums 7338946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski uint32_t cur_dyn_offset = total_dynamic_descriptors; 7339ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski for (uint32_t d = 0; d < descriptor_set->GetTotalDescriptorCount(); d++) { 7340ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski if (descriptor_set->GetTypeFromGlobalIndex(d) == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) { 7341ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski if (vk_safe_modulo( 7342ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski pDynamicOffsets[cur_dyn_offset], 7343ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski dev_data->phys_dev_properties.properties.limits.minUniformBufferOffsetAlignment) != 0) { 7344946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= log_msg( 7345ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 7346ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, VALIDATION_ERROR_00978, "DS", 7347ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski "vkCmdBindDescriptorSets(): pDynamicOffsets[%d] is %d but must be a multiple of " 7348ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski "device limit minUniformBufferOffsetAlignment 0x%" PRIxLEAST64 ". %s", 7349ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski cur_dyn_offset, pDynamicOffsets[cur_dyn_offset], 7350ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski dev_data->phys_dev_properties.properties.limits.minUniformBufferOffsetAlignment, 7351ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski validation_error_map[VALIDATION_ERROR_00978]); 7352ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } 7353ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski cur_dyn_offset++; 7354ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } else if (descriptor_set->GetTypeFromGlobalIndex(d) == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) { 7355ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski if (vk_safe_modulo( 7356ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski pDynamicOffsets[cur_dyn_offset], 7357ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski dev_data->phys_dev_properties.properties.limits.minStorageBufferOffsetAlignment) != 0) { 7358946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= log_msg( 7359ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 7360ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, VALIDATION_ERROR_00978, "DS", 7361ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski "vkCmdBindDescriptorSets(): pDynamicOffsets[%d] is %d but must be a multiple of " 7362ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski "device limit minStorageBufferOffsetAlignment 0x%" PRIxLEAST64 ". %s", 7363ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski cur_dyn_offset, pDynamicOffsets[cur_dyn_offset], 7364ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski dev_data->phys_dev_properties.properties.limits.minStorageBufferOffsetAlignment, 7365ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski validation_error_map[VALIDATION_ERROR_00978]); 7366ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } 7367ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski cur_dyn_offset++; 7368ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } 736972d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis } 7370ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski 7371946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->lastBound[pipelineBindPoint].dynamicOffsets[firstSet + set_idx] = 7372946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski std::vector<uint32_t>(pDynamicOffsets + total_dynamic_descriptors, 7373946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski pDynamicOffsets + total_dynamic_descriptors + set_dynamic_descriptor_count); 7374ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski // Keep running total of dynamic descriptor count to verify at the end 7375946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski total_dynamic_descriptors += set_dynamic_descriptor_count; 737672d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis } 737772d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis } 7378ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } else { 7379946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= log_msg( 7380ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, 7381ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski (uint64_t)pDescriptorSets[set_idx], __LINE__, DRAWSTATE_INVALID_SET, "DS", 7382ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski "Attempt to bind descriptor set 0x%" PRIxLEAST64 " that doesn't exist!", (uint64_t)pDescriptorSets[set_idx]); 7383ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } 7384946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski UpdateCmdBufferLastCmd(cb_state, CMD_BINDDESCRIPTORSETS); 7385ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski // For any previously bound sets, need to set them to "invalid" if they were disturbed by this update 7386ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski if (firstSet > 0) { // Check set #s below the first bound set 7387ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski for (uint32_t i = 0; i < firstSet; ++i) { 7388946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (cb_state->lastBound[pipelineBindPoint].boundDescriptorSets[i] && 7389946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski !verify_set_layout_compatibility(dev_data, cb_state->lastBound[pipelineBindPoint].boundDescriptorSets[i], 7390946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski pipeline_layout, i, error_string)) { 7391946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= log_msg( 7392ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, 7393ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, 7394946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski (uint64_t)cb_state->lastBound[pipelineBindPoint].boundDescriptorSets[i], __LINE__, DRAWSTATE_NONE, "DS", 7395ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski "DescriptorSet 0x%" PRIxLEAST64 7396ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski " previously bound as set #%u was disturbed by newly bound pipelineLayout (0x%" PRIxLEAST64 ")", 7397946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski (uint64_t)cb_state->lastBound[pipelineBindPoint].boundDescriptorSets[i], i, (uint64_t)layout); 7398946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->lastBound[pipelineBindPoint].boundDescriptorSets[i] = VK_NULL_HANDLE; 73995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 74005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 74015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7402ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski // Check if newly last bound set invalidates any remaining bound sets 7403946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if ((cb_state->lastBound[pipelineBindPoint].boundDescriptorSets.size() - 1) > (last_set_index)) { 7404946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (old_final_bound_set && 7405946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski !verify_set_layout_compatibility(dev_data, old_final_bound_set, pipeline_layout, last_set_index, 7406946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski error_string)) { 7407946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski auto old_set = old_final_bound_set->GetSet(); 7408946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, 7409946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, reinterpret_cast<uint64_t &>(old_set), __LINE__, 7410946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski DRAWSTATE_NONE, "DS", "DescriptorSet 0x%" PRIxLEAST64 7411946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski " previously bound as set #%u is incompatible with set 0x%" PRIxLEAST64 7412946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski " newly bound as set #%u so set #%u and any subsequent sets were " 7413946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "disturbed by newly bound pipelineLayout (0x%" PRIxLEAST64 ")", 7414946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski reinterpret_cast<uint64_t &>(old_set), last_set_index, 7415946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski (uint64_t)cb_state->lastBound[pipelineBindPoint].boundDescriptorSets[last_set_index], 7416946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski last_set_index, last_set_index + 1, (uint64_t)layout); 7417946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->lastBound[pipelineBindPoint].boundDescriptorSets.resize(last_set_index + 1); 7418ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } 7419787f29d93dee194c015789cf61c079504c980572Tobin Ehlis } 7420ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } 7421ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski // dynamicOffsetCount must equal the total number of dynamic descriptors in the sets being bound 7422946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (total_dynamic_descriptors != dynamicOffsetCount) { 7423946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 7424946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski (uint64_t)commandBuffer, __LINE__, VALIDATION_ERROR_00975, "DS", 7425946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "Attempting to bind %u descriptorSets with %u dynamic descriptors, but dynamicOffsetCount " 7426946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "is %u. It should exactly match the number of dynamic descriptors. %s", 7427946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski setCount, total_dynamic_descriptors, dynamicOffsetCount, validation_error_map[VALIDATION_ERROR_00975]); 74285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 74295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7430b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7431946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (!skip) 74324a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdBindDescriptorSets(commandBuffer, pipelineBindPoint, layout, firstSet, setCount, 74334a0754042cf090e131e9e769d8a3633c228625beChris Forbes pDescriptorSets, dynamicOffsetCount, pDynamicOffsets); 74345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 74355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7436bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBindIndexBuffer(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, 7437bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkIndexType indexType) { 7438946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski bool skip = false; 743956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7440593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis // TODO : Somewhere need to verify that IBs have correct usage state flagged 7441b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7442b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski 74439a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto buffer_state = GetBufferState(dev_data, buffer); 74449a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, commandBuffer); 74455cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis if (cb_node && buffer_state) { 7446baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip |= ValidateCmdQueueFlags(dev_data, cb_node, "vkCmdBindIndexBuffer()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_01357); 7447946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ValidateCmd(dev_data, cb_node, CMD_BINDINDEXBUFFER, "vkCmdBindIndexBuffer()"); 7448946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ValidateMemoryIsBoundToBuffer(dev_data, buffer_state, "vkCmdBindIndexBuffer()", VALIDATION_ERROR_02543); 7449ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski std::function<bool()> function = [=]() { 7450ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski return ValidateBufferMemoryIsValid(dev_data, buffer_state, "vkCmdBindIndexBuffer()"); 7451ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski }; 7452ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski cb_node->validate_functions.push_back(function); 7453ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski UpdateCmdBufferLastCmd(cb_node, CMD_BINDINDEXBUFFER); 7454ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski VkDeviceSize offset_align = 0; 7455ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski switch (indexType) { 7456ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski case VK_INDEX_TYPE_UINT16: 7457ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski offset_align = 2; 7458ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski break; 7459ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski case VK_INDEX_TYPE_UINT32: 7460ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski offset_align = 4; 7461ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski break; 7462ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski default: 7463ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski // ParamChecker should catch bad enum, we'll also throw alignment error below if offset_align stays 0 7464ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski break; 74655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7466ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski if (!offset_align || (offset % offset_align)) { 7467df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 7468df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(commandBuffer), __LINE__, DRAWSTATE_VTX_INDEX_ALIGNMENT_ERROR, "DS", 7469946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "vkCmdBindIndexBuffer() offset (0x%" PRIxLEAST64 ") does not fall on alignment (%s) boundary.", offset, 7470946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski string_VkIndexType(indexType)); 7471ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } 7472ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski cb_node->status |= CBSTATUS_INDEX_BUFFER_BOUND; 7473ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } else { 7474ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis assert(0); 74755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7476b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7477946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdBindIndexBuffer(commandBuffer, buffer, offset, indexType); 74785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 74795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 74805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisvoid updateResourceTracking(GLOBAL_CB_NODE *pCB, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer *pBuffers) { 74815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t end = firstBinding + bindingCount; 74825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB->currentDrawData.buffers.size() < end) { 74835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->currentDrawData.buffers.resize(end); 74845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 74855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < bindingCount; ++i) { 74865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->currentDrawData.buffers[i + firstBinding] = pBuffers[i]; 74875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 74885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 74895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7490e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic inline void updateResourceTrackingOnDraw(GLOBAL_CB_NODE *pCB) { pCB->drawData.push_back(pCB->currentDrawData); } 74915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7492bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBindVertexBuffers(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, 7493bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkBuffer *pBuffers, const VkDeviceSize *pOffsets) { 7494946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski bool skip = false; 749556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7496593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis // TODO : Somewhere need to verify that VBs have correct usage state flagged 7497b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7498b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski 74999a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, commandBuffer); 75009f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis if (cb_node) { 7501baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip |= ValidateCmdQueueFlags(dev_data, cb_node, "vkCmdBindVertexBuffers()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_01423); 7502baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip |= ValidateCmd(dev_data, cb_node, CMD_BINDVERTEXBUFFER, "vkCmdBindVertexBuffers()"); 7503ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski for (uint32_t i = 0; i < bindingCount; ++i) { 7504ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski auto buffer_state = GetBufferState(dev_data, pBuffers[i]); 7505ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski assert(buffer_state); 7506946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ValidateMemoryIsBoundToBuffer(dev_data, buffer_state, "vkCmdBindVertexBuffers()", VALIDATION_ERROR_02546); 7507ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski std::function<bool()> function = [=]() { 7508ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski return ValidateBufferMemoryIsValid(dev_data, buffer_state, "vkCmdBindVertexBuffers()"); 7509ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski }; 7510ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski cb_node->validate_functions.push_back(function); 75115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7512ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski UpdateCmdBufferLastCmd(cb_node, CMD_BINDVERTEXBUFFER); 7513ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski updateResourceTracking(cb_node, firstBinding, bindingCount, pBuffers); 75145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 75157828015969ab31ee01d597f0288cbb124b637fcdMark Lobodzinski assert(0); 75165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7517b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7518946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdBindVertexBuffers(commandBuffer, firstBinding, bindingCount, pBuffers, pOffsets); 75195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 75205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 752125002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// Expects global_lock to be held by caller 75225569d6457ac22e7d245f3cdee045e71ffbc8b06eTobin Ehlisstatic void MarkStoreImagesAndBuffersAsWritten(layer_data *dev_data, GLOBAL_CB_NODE *pCB) { 75237a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis for (auto imageView : pCB->updateImages) { 75249a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto view_state = GetImageViewState(dev_data, imageView); 7525cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!view_state) continue; 7526249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis 75279a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_state = GetImageState(dev_data, view_state->create_info.image); 75281facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis assert(image_state); 7529e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves std::function<bool()> function = [=]() { 75301facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis SetImageMemoryValid(dev_data, image_state, true); 7531e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves return false; 75327a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis }; 75337a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis pCB->validate_functions.push_back(function); 75347a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis } 75357a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis for (auto buffer : pCB->updateBuffers) { 75369a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto buffer_state = GetBufferState(dev_data, buffer); 75375cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis assert(buffer_state); 7538e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves std::function<bool()> function = [=]() { 75395cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis SetBufferMemoryValid(dev_data, buffer_state, true); 7540e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves return false; 75417a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis }; 75427a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis pCB->validate_functions.push_back(function); 75435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 75445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 75455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7546ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis// Generic function to handle validation for all CmdDraw* type functions 7547ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool ValidateCmdDrawType(layer_data *dev_data, VkCommandBuffer cmd_buffer, bool indexed, VkPipelineBindPoint bind_point, 7548baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt CMD_TYPE cmd_type, GLOBAL_CB_NODE **cb_state, const char *caller, VkQueueFlags queue_flags, 7549baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt UNIQUE_VALIDATION_ERROR_CODE queue_flag_code, UNIQUE_VALIDATION_ERROR_CODE msg_code, 7550baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt UNIQUE_VALIDATION_ERROR_CODE const dynamic_state_msg_code) { 755158b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis bool skip = false; 75529a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *cb_state = GetCBNode(dev_data, cmd_buffer); 755358b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis if (*cb_state) { 7554baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip |= ValidateCmdQueueFlags(dev_data, *cb_state, caller, queue_flags, queue_flag_code); 7555ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis skip |= ValidateCmd(dev_data, *cb_state, cmd_type, caller); 75564f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes skip |= ValidateDrawState(dev_data, *cb_state, indexed, bind_point, caller, dynamic_state_msg_code); 755725d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis skip |= (VK_PIPELINE_BIND_POINT_GRAPHICS == bind_point) ? outsideRenderPass(dev_data, *cb_state, caller, msg_code) 755825d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis : insideRenderPass(dev_data, *cb_state, caller, msg_code); 755958b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis } 756058b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis return skip; 756158b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis} 756258b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis 756325d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis// Generic function to handle state update for all CmdDraw* and CmdDispatch* type functions 7564ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void UpdateStateCmdDrawDispatchType(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point, 7565ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis CMD_TYPE cmd_type) { 7566ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis UpdateDrawState(dev_data, cb_state, bind_point); 75672f921d33544c162dcb726fc3c7b915e89c02ff24Tobin Ehlis MarkStoreImagesAndBuffersAsWritten(dev_data, cb_state); 75681ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(cb_state, cmd_type); 756925d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis} 757025d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis 7571ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis// Generic function to handle state update for all CmdDraw* type functions 7572ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void UpdateStateCmdDrawType(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point, 7573ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis CMD_TYPE cmd_type, DRAW_TYPE draw_type) { 7574ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis UpdateStateCmdDrawDispatchType(dev_data, cb_state, bind_point, cmd_type); 7575c0b225e42808ba8fada7a2f67ecd662e376ccf15Tobin Ehlis updateResourceTrackingOnDraw(cb_state); 7576ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis cb_state->drawCount[draw_type]++; 7577ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis} 7578ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis 7579ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool PreCallValidateCmdDraw(layer_data *dev_data, VkCommandBuffer cmd_buffer, bool indexed, VkPipelineBindPoint bind_point, 7580ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis GLOBAL_CB_NODE **cb_state, const char *caller) { 7581baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt return ValidateCmdDrawType(dev_data, cmd_buffer, indexed, bind_point, CMD_DRAW, cb_state, caller, VK_QUEUE_GRAPHICS_BIT, 7582baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt VALIDATION_ERROR_01364, VALIDATION_ERROR_01365, VALIDATION_ERROR_02203); 7583ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis} 7584ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis 7585ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void PostCallRecordCmdDraw(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point) { 7586ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis UpdateStateCmdDrawType(dev_data, cb_state, bind_point, CMD_DRAW, DRAW); 7587c0b225e42808ba8fada7a2f67ecd662e376ccf15Tobin Ehlis} 7588c0b225e42808ba8fada7a2f67ecd662e376ccf15Tobin Ehlis 758989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount, 759089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu uint32_t firstVertex, uint32_t firstInstance) { 759156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 759258b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis GLOBAL_CB_NODE *cb_state = nullptr; 7593b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7594ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis bool skip = PreCallValidateCmdDraw(dev_data, commandBuffer, false, VK_PIPELINE_BIND_POINT_GRAPHICS, &cb_state, "vkCmdDraw()"); 7595b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 759658b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis if (!skip) { 75974a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdDraw(commandBuffer, vertexCount, instanceCount, firstVertex, firstInstance); 7598c0b225e42808ba8fada7a2f67ecd662e376ccf15Tobin Ehlis lock.lock(); 7599ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis PostCallRecordCmdDraw(dev_data, cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS); 7600c0b225e42808ba8fada7a2f67ecd662e376ccf15Tobin Ehlis lock.unlock(); 7601c0b225e42808ba8fada7a2f67ecd662e376ccf15Tobin Ehlis } 76025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 76035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7604ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool PreCallValidateCmdDrawIndexed(layer_data *dev_data, VkCommandBuffer cmd_buffer, bool indexed, 7605ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis VkPipelineBindPoint bind_point, GLOBAL_CB_NODE **cb_state, const char *caller) { 7606baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt return ValidateCmdDrawType(dev_data, cmd_buffer, indexed, bind_point, CMD_DRAWINDEXED, cb_state, caller, VK_QUEUE_GRAPHICS_BIT, 7607baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt VALIDATION_ERROR_01371, VALIDATION_ERROR_01372, VALIDATION_ERROR_02216); 7608ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis} 7609ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis 7610ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void PostCallRecordCmdDrawIndexed(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point) { 7611ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis UpdateStateCmdDrawType(dev_data, cb_state, bind_point, CMD_DRAWINDEXED, DRAW_INDEXED); 7612ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis} 7613ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis 7614bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount, 7615bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance) { 761656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7617ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis GLOBAL_CB_NODE *cb_state = nullptr; 7618b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7619ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis bool skip = PreCallValidateCmdDrawIndexed(dev_data, commandBuffer, true, VK_PIPELINE_BIND_POINT_GRAPHICS, &cb_state, 7620ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis "vkCmdDrawIndexed()"); 7621b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7622ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis if (!skip) { 76234a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdDrawIndexed(commandBuffer, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance); 7624ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis lock.lock(); 7625ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis PostCallRecordCmdDrawIndexed(dev_data, cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS); 7626ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis lock.unlock(); 7627ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis } 76285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 76295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7630ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool PreCallValidateCmdDrawIndirect(layer_data *dev_data, VkCommandBuffer cmd_buffer, VkBuffer buffer, bool indexed, 7631ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis VkPipelineBindPoint bind_point, GLOBAL_CB_NODE **cb_state, BUFFER_STATE **buffer_state, 7632ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis const char *caller) { 76334f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes bool skip = ValidateCmdDrawType(dev_data, cmd_buffer, indexed, bind_point, CMD_DRAWINDIRECT, cb_state, caller, 7634baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_01380, VALIDATION_ERROR_01381, VALIDATION_ERROR_02234); 76359a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *buffer_state = GetBufferState(dev_data, buffer); 763635ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis skip |= ValidateMemoryIsBoundToBuffer(dev_data, *buffer_state, caller, VALIDATION_ERROR_02544); 763713c4316d0072cbc5bf3cd729abef4d114f3c96edMark Lobodzinski // TODO: If the drawIndirectFirstInstance feature is not enabled, all the firstInstance members of the 763813c4316d0072cbc5bf3cd729abef4d114f3c96edMark Lobodzinski // VkDrawIndirectCommand structures accessed by this command must be 0, which will require access to the contents of 'buffer'. 7639d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis return skip; 7640d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis} 7641d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis 7642ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void PostCallRecordCmdDrawIndirect(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point, 7643ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis BUFFER_STATE *buffer_state) { 7644ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis UpdateStateCmdDrawType(dev_data, cb_state, bind_point, CMD_DRAWINDIRECT, DRAW_INDIRECT); 7645d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis AddCommandBufferBindingBuffer(dev_data, cb_state, buffer_state); 7646d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis} 7647d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis 7648bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count, 7649bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski uint32_t stride) { 765056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7651d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis GLOBAL_CB_NODE *cb_state = nullptr; 7652d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis BUFFER_STATE *buffer_state = nullptr; 7653b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7654872a2f0ca3ffdeddfa7483e777191fa64b853892Tony Barbour bool skip = PreCallValidateCmdDrawIndirect(dev_data, commandBuffer, buffer, false, VK_PIPELINE_BIND_POINT_GRAPHICS, &cb_state, 7655ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis &buffer_state, "vkCmdDrawIndirect()"); 7656b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7657d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis if (!skip) { 76584a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdDrawIndirect(commandBuffer, buffer, offset, count, stride); 7659d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis lock.lock(); 7660ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis PostCallRecordCmdDrawIndirect(dev_data, cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, buffer_state); 7661d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis lock.unlock(); 7662d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis } 76635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 76645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7665ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool PreCallValidateCmdDrawIndexedIndirect(layer_data *dev_data, VkCommandBuffer cmd_buffer, VkBuffer buffer, bool indexed, 7666ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis VkPipelineBindPoint bind_point, GLOBAL_CB_NODE **cb_state, 7667ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis BUFFER_STATE **buffer_state, const char *caller) { 7668ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis bool skip = ValidateCmdDrawType(dev_data, cmd_buffer, indexed, bind_point, CMD_DRAWINDEXEDINDIRECT, cb_state, caller, 7669baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_01392, VALIDATION_ERROR_01393, VALIDATION_ERROR_02272); 76709a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *buffer_state = GetBufferState(dev_data, buffer); 767135ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis skip |= ValidateMemoryIsBoundToBuffer(dev_data, *buffer_state, caller, VALIDATION_ERROR_02545); 767213c4316d0072cbc5bf3cd729abef4d114f3c96edMark Lobodzinski // TODO: If the drawIndirectFirstInstance feature is not enabled, all the firstInstance members of the 767313c4316d0072cbc5bf3cd729abef4d114f3c96edMark Lobodzinski // VkDrawIndexedIndirectCommand structures accessed by this command must be 0, which will require access to the contents of 767413c4316d0072cbc5bf3cd729abef4d114f3c96edMark Lobodzinski // 'buffer'. 76750c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis return skip; 76760c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis} 76770c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis 7678ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void PostCallRecordCmdDrawIndexedIndirect(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point, 7679ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis BUFFER_STATE *buffer_state) { 7680ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis UpdateStateCmdDrawType(dev_data, cb_state, bind_point, CMD_DRAWINDEXEDINDIRECT, DRAW_INDEXED_INDIRECT); 76810c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis AddCommandBufferBindingBuffer(dev_data, cb_state, buffer_state); 76820c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis} 76830c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis 7684bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, 7685bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski uint32_t count, uint32_t stride) { 768656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 76870c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis GLOBAL_CB_NODE *cb_state = nullptr; 76880c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis BUFFER_STATE *buffer_state = nullptr; 7689b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 76900c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis bool skip = PreCallValidateCmdDrawIndexedIndirect(dev_data, commandBuffer, buffer, true, VK_PIPELINE_BIND_POINT_GRAPHICS, 7691ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis &cb_state, &buffer_state, "vkCmdDrawIndexedIndirect()"); 7692b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 76930c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis if (!skip) { 76944a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdDrawIndexedIndirect(commandBuffer, buffer, offset, count, stride); 76950c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis lock.lock(); 7696ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis PostCallRecordCmdDrawIndexedIndirect(dev_data, cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, buffer_state); 76970c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis lock.unlock(); 76980c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis } 76995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 77005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7701ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool PreCallValidateCmdDispatch(layer_data *dev_data, VkCommandBuffer cmd_buffer, bool indexed, 7702ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis VkPipelineBindPoint bind_point, GLOBAL_CB_NODE **cb_state, const char *caller) { 7703baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt return ValidateCmdDrawType(dev_data, cmd_buffer, indexed, bind_point, CMD_DISPATCH, cb_state, caller, VK_QUEUE_COMPUTE_BIT, 7704baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt VALIDATION_ERROR_01561, VALIDATION_ERROR_01562, VALIDATION_ERROR_UNDEFINED); 770525d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis} 770625d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis 7707ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void PostCallRecordCmdDispatch(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point) { 7708ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis UpdateStateCmdDrawDispatchType(dev_data, cb_state, bind_point, CMD_DISPATCH); 770925d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis} 771025d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis 771189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z) { 771256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 771325d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis GLOBAL_CB_NODE *cb_state = nullptr; 7714b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7715ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis bool skip = 7716ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis PreCallValidateCmdDispatch(dev_data, commandBuffer, false, VK_PIPELINE_BIND_POINT_COMPUTE, &cb_state, "vkCmdDispatch()"); 7717b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 771825d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis if (!skip) { 77194a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdDispatch(commandBuffer, x, y, z); 772025d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis lock.lock(); 7721ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis PostCallRecordCmdDispatch(dev_data, cb_state, VK_PIPELINE_BIND_POINT_COMPUTE); 772225d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis lock.unlock(); 772325d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis } 77245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 77255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7726ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool PreCallValidateCmdDispatchIndirect(layer_data *dev_data, VkCommandBuffer cmd_buffer, VkBuffer buffer, bool indexed, 7727ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis VkPipelineBindPoint bind_point, GLOBAL_CB_NODE **cb_state, 7728ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis BUFFER_STATE **buffer_state, const char *caller) { 7729baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt bool skip = 7730baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt ValidateCmdDrawType(dev_data, cmd_buffer, indexed, bind_point, CMD_DISPATCHINDIRECT, cb_state, caller, VK_QUEUE_COMPUTE_BIT, 7731baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt VALIDATION_ERROR_01568, VALIDATION_ERROR_01569, VALIDATION_ERROR_UNDEFINED); 77329a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *buffer_state = GetBufferState(dev_data, buffer); 773335ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis skip |= ValidateMemoryIsBoundToBuffer(dev_data, *buffer_state, caller, VALIDATION_ERROR_02547); 773479c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis return skip; 773579c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis} 773679c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis 7737ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void PostCallRecordCmdDispatchIndirect(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point, 7738ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis BUFFER_STATE *buffer_state) { 7739ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis UpdateStateCmdDrawDispatchType(dev_data, cb_state, bind_point, CMD_DISPATCHINDIRECT); 774079c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis AddCommandBufferBindingBuffer(dev_data, cb_state, buffer_state); 774179c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis} 774279c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis 7743bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset) { 774456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 774579c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis GLOBAL_CB_NODE *cb_state = nullptr; 774679c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis BUFFER_STATE *buffer_state = nullptr; 7747b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 77487433ab60c7ff16d37edb0f8b17b606ccd363e210Tobin Ehlis bool skip = PreCallValidateCmdDispatchIndirect(dev_data, commandBuffer, buffer, false, VK_PIPELINE_BIND_POINT_COMPUTE, 7749ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis &cb_state, &buffer_state, "vkCmdDispatchIndirect()"); 7750b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 775179c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis if (!skip) { 77524a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdDispatchIndirect(commandBuffer, buffer, offset); 775379c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis lock.lock(); 7754ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis PostCallRecordCmdDispatchIndirect(dev_data, cb_state, VK_PIPELINE_BIND_POINT_COMPUTE, buffer_state); 775579c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis lock.unlock(); 775679c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis } 77575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 77585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 775989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdCopyBuffer(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer, 776089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu uint32_t regionCount, const VkBufferCopy *pRegions) { 7761c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7762b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7763ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis 7764c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski auto cb_node = GetCBNode(device_data, commandBuffer); 7765c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski auto src_buffer_state = GetBufferState(device_data, srcBuffer); 7766c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski auto dst_buffer_state = GetBufferState(device_data, dstBuffer); 7767593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 7768c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski if (cb_node && src_buffer_state && dst_buffer_state) { 7769c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski bool skip = PreCallValidateCmdCopyBuffer(device_data, cb_node, src_buffer_state, dst_buffer_state); 7770c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski if (!skip) { 7771c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski PreCallRecordCmdCopyBuffer(device_data, cb_node, src_buffer_state, dst_buffer_state); 7772c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski lock.unlock(); 7773c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski device_data->dispatch_table.CmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, regionCount, pRegions); 7774c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski } 7775ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } else { 7776c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski lock.unlock(); 7777ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis assert(0); 77785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 77795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 77805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7781bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdCopyImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, 7782bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, 7783bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkImageCopy *pRegions) { 77846a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski bool skip = false; 77856a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7786b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7787249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis 77886a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski auto cb_node = GetCBNode(device_data, commandBuffer); 77896a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski auto src_image_state = GetImageState(device_data, srcImage); 77906a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski auto dst_image_state = GetImageState(device_data, dstImage); 77911facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis if (cb_node && src_image_state && dst_image_state) { 77926a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski skip = PreCallValidateCmdCopyImage(device_data, cb_node, src_image_state, dst_image_state, regionCount, pRegions, 77936a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski srcImageLayout, dstImageLayout); 77946a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski if (!skip) { 7795a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis PreCallRecordCmdCopyImage(device_data, cb_node, src_image_state, dst_image_state, regionCount, pRegions, srcImageLayout, 7796a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis dstImageLayout); 77976a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski lock.unlock(); 77986a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski device_data->dispatch_table.CmdCopyImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, 77996a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski pRegions); 78005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7801249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis } else { 78026a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski lock.unlock(); 7803249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis assert(0); 78045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 78055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 78065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7807eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski// Validate that an image's sampleCount matches the requirement for a specific API call 780860568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinskibool ValidateImageSampleCount(layer_data *dev_data, IMAGE_STATE *image_state, VkSampleCountFlagBits sample_count, 780960568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski const char *location, UNIQUE_VALIDATION_ERROR_CODE msgCode) { 7810eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski bool skip = false; 78111facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis if (image_state->createInfo.samples != sample_count) { 781255eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen skip = 781355eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 781455eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen reinterpret_cast<uint64_t &>(image_state->image), 0, msgCode, "DS", 781555eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen "%s for image 0x%" PRIxLEAST64 " was created with a sample count of %s but must be %s. %s", location, 781655eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen reinterpret_cast<uint64_t &>(image_state->image), string_VkSampleCountFlagBits(image_state->createInfo.samples), 781755eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen string_VkSampleCountFlagBits(sample_count), validation_error_map[msgCode]); 7818eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski } 7819eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski return skip; 7820eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski} 7821eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski 7822bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBlitImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, 7823bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, 7824bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkImageBlit *pRegions, VkFilter filter) { 782556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7826b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7827593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 78289a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, commandBuffer); 78299a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto src_image_state = GetImageState(dev_data, srcImage); 78309a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto dst_image_state = GetImageState(dev_data, dstImage); 78310dc51740dbd7b9f0ba7c071e0bf96f63d6d48c85Mark Lobodzinski 7832055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski bool skip = PreCallValidateCmdBlitImage(dev_data, cb_node, src_image_state, dst_image_state, regionCount, pRegions, filter); 78330dc51740dbd7b9f0ba7c071e0bf96f63d6d48c85Mark Lobodzinski 7834dca02371c9531e7a9a2a51decae1db4d297862c4Mark Lobodzinski if (!skip) { 7835eebd811afd800663f15fda8fc71bc203a03fe294Mark Lobodzinski PreCallRecordCmdBlitImage(dev_data, cb_node, src_image_state, dst_image_state); 7836eebd811afd800663f15fda8fc71bc203a03fe294Mark Lobodzinski lock.unlock(); 78374a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdBlitImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, 78384a0754042cf090e131e9e769d8a3633c228625beChris Forbes pRegions, filter); 78390dc51740dbd7b9f0ba7c071e0bf96f63d6d48c85Mark Lobodzinski } 78405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 78415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7842bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdCopyBufferToImage(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage, 7843bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkImageLayout dstImageLayout, uint32_t regionCount, 7844bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkBufferImageCopy *pRegions) { 7845940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7846b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7847940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski bool skip = false; 7848940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski auto cb_node = GetCBNode(device_data, commandBuffer); 7849940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski auto src_buffer_state = GetBufferState(device_data, srcBuffer); 7850940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski auto dst_image_state = GetImageState(device_data, dstImage); 7851940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski if (cb_node && src_buffer_state && dst_image_state) { 7852940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski skip = PreCallValidateCmdCopyBufferToImage(device_data, dstImageLayout, cb_node, src_buffer_state, dst_image_state, 785371c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski regionCount, pRegions, "vkCmdCopyBufferToImage()"); 7854ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } else { 7855d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski lock.unlock(); 7856ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis assert(0); 7857e4d82c37d6c861b388dbc80297c18d6255858cb4Dave Houlton // TODO: report VU01244 here, or put in object tracker? 78585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7859940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski if (!skip) { 7860a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis PreCallRecordCmdCopyBufferToImage(device_data, cb_node, src_buffer_state, dst_image_state, regionCount, pRegions, 7861a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis dstImageLayout); 7862d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski lock.unlock(); 7863940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski device_data->dispatch_table.CmdCopyBufferToImage(commandBuffer, srcBuffer, dstImage, dstImageLayout, regionCount, pRegions); 7864d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski } 78655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 78665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7867bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdCopyImageToBuffer(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, 7868bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkBuffer dstBuffer, uint32_t regionCount, const VkBufferImageCopy *pRegions) { 7869940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski bool skip = false; 7870940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7871b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7872593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 7873940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski auto cb_node = GetCBNode(device_data, commandBuffer); 7874940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski auto src_image_state = GetImageState(device_data, srcImage); 7875940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski auto dst_buffer_state = GetBufferState(device_data, dstBuffer); 7876940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski if (cb_node && src_image_state && dst_buffer_state) { 7877940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski skip = PreCallValidateCmdCopyImageToBuffer(device_data, srcImageLayout, cb_node, src_image_state, dst_buffer_state, 787871c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski regionCount, pRegions, "vkCmdCopyImageToBuffer()"); 7879ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } else { 7880d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski lock.unlock(); 7881ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis assert(0); 7882e4d82c37d6c861b388dbc80297c18d6255858cb4Dave Houlton // TODO: report VU01262 here, or put in object tracker? 78835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7884940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski if (!skip) { 7885a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis PreCallRecordCmdCopyImageToBuffer(device_data, cb_node, src_image_state, dst_buffer_state, regionCount, pRegions, 7886a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis srcImageLayout); 7887d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski lock.unlock(); 7888940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski device_data->dispatch_table.CmdCopyImageToBuffer(commandBuffer, srcImage, srcImageLayout, dstBuffer, regionCount, pRegions); 7889d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski } 78905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 78915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7892bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdUpdateBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, 7893bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDeviceSize dataSize, const uint32_t *pData) { 789483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 789556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7896b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7897593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 78989a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, commandBuffer); 78999a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto dst_buff_state = GetBufferState(dev_data, dstBuffer); 79005cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis if (cb_node && dst_buff_state) { 790135ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, dst_buff_state, "vkCmdUpdateBuffer()", VALIDATION_ERROR_02530); 7902ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis // Update bindings between buffer and cmd buffer 79035cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis AddCommandBufferBindingBuffer(dev_data, cb_node, dst_buff_state); 7904ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis // Validate that DST buffer has correct usage flags set 79055cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis skip_call |= ValidateBufferUsageFlags(dev_data, dst_buff_state, VK_BUFFER_USAGE_TRANSFER_DST_BIT, true, 79061b8a6bd9260c52ca6c6cfe1e34f142f93e1e2cc6Jeremy Hayes VALIDATION_ERROR_01146, "vkCmdUpdateBuffer()", "VK_BUFFER_USAGE_TRANSFER_DST_BIT"); 7907e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves std::function<bool()> function = [=]() { 79085cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis SetBufferMemoryValid(dev_data, dst_buff_state, true); 7909e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves return false; 79105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis }; 79119f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis cb_node->validate_functions.push_back(function); 7912593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 7913baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip_call |= 7914baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt ValidateCmdQueueFlags(dev_data, cb_node, "vkCmdUpdateBuffer()", 7915baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt VK_QUEUE_TRANSFER_BIT | VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, VALIDATION_ERROR_01154); 791629f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, cb_node, CMD_UPDATEBUFFER, "vkCmdUpdateBuffer()"); 79171ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(cb_node, CMD_UPDATEBUFFER); 7918ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen skip_call |= insideRenderPass(dev_data, cb_node, "vkCmdUpdateBuffer()", VALIDATION_ERROR_01155); 7919ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } else { 7920ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis assert(0); 79215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7922b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7923cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.CmdUpdateBuffer(commandBuffer, dstBuffer, dstOffset, dataSize, pData); 79245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 79255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7926bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdFillBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, 7927bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDeviceSize size, uint32_t data) { 792823bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7929b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 793023bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski auto cb_node = GetCBNode(device_data, commandBuffer); 793123bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski auto buffer_state = GetBufferState(device_data, dstBuffer); 7932593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 793323bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski if (cb_node && buffer_state) { 793423bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski bool skip = PreCallValidateCmdFillBuffer(device_data, cb_node, buffer_state); 793523bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski if (!skip) { 793623bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski PreCallRecordCmdFillBuffer(device_data, cb_node, buffer_state); 793723bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski lock.unlock(); 793823bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski device_data->dispatch_table.CmdFillBuffer(commandBuffer, dstBuffer, dstOffset, size, data); 793923bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski } 7940ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } else { 794123bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski lock.unlock(); 7942ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis assert(0); 79435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 79445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 79455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 79464028af23e688ab5730f48ab2244dd042e2eefaedMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdClearAttachments(VkCommandBuffer commandBuffer, uint32_t attachmentCount, 79474028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski const VkClearAttachment *pAttachments, uint32_t rectCount, 79484028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski const VkClearRect *pRects) { 79494028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski bool skip = false; 795056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 79514028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski { 79524028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski std::lock_guard<std::mutex> lock(global_lock); 79534028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski skip = PreCallValidateCmdClearAttachments(dev_data, commandBuffer, attachmentCount, pAttachments, rectCount, pRects); 79544028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski } 7955cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdClearAttachments(commandBuffer, attachmentCount, pAttachments, rectCount, pRects); 79565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 79575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 79580482c55760707900fcd072f6895c121bcf055f6eMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdClearColorImage(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, 79590482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski const VkClearColorValue *pColor, uint32_t rangeCount, 79600482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski const VkImageSubresourceRange *pRanges) { 796156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7962b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 79630482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski 79640482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski bool skip = PreCallValidateCmdClearColorImage(dev_data, commandBuffer, image, imageLayout, rangeCount, pRanges); 79650482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski if (!skip) { 79660482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski PreCallRecordCmdClearImage(dev_data, commandBuffer, image, imageLayout, rangeCount, pRanges, CMD_CLEARCOLORIMAGE); 79670482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski lock.unlock(); 79680482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski dev_data->dispatch_table.CmdClearColorImage(commandBuffer, image, imageLayout, pColor, rangeCount, pRanges); 79690482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski } 79700482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski} 79710482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski 79720482c55760707900fcd072f6895c121bcf055f6eMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdClearDepthStencilImage(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, 79730482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski const VkClearDepthStencilValue *pDepthStencil, uint32_t rangeCount, 79740482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski const VkImageSubresourceRange *pRanges) { 797556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 79760482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski std::unique_lock<std::mutex> lock(global_lock); 79770482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski 79780482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski bool skip = PreCallValidateCmdClearDepthStencilImage(dev_data, commandBuffer, image, imageLayout, rangeCount, pRanges); 79790482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski if (!skip) { 79800482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski PreCallRecordCmdClearImage(dev_data, commandBuffer, image, imageLayout, rangeCount, pRanges, CMD_CLEARDEPTHSTENCILIMAGE); 79810482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski lock.unlock(); 79820482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski dev_data->dispatch_table.CmdClearDepthStencilImage(commandBuffer, image, imageLayout, pDepthStencil, rangeCount, pRanges); 79837f8aa8f5abceedbb599ef69af1dfbb38c0df2660Slawomir Cygan } 79845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 79855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7986bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdResolveImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, 7987bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, 7988bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkImageResolve *pRegions) { 798956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7990b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7991593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 79929a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, commandBuffer); 79939a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto src_image_state = GetImageState(dev_data, srcImage); 79949a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto dst_image_state = GetImageState(dev_data, dstImage); 799509fe5ac5edaec7f0dbcc9fd696e68194569aea89Mark Lobodzinski 799625f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski bool skip = PreCallValidateCmdResolveImage(dev_data, cb_node, src_image_state, dst_image_state, regionCount, pRegions); 799709fe5ac5edaec7f0dbcc9fd696e68194569aea89Mark Lobodzinski 799809fe5ac5edaec7f0dbcc9fd696e68194569aea89Mark Lobodzinski if (!skip) { 79996c0400e625554ce7fddb833eeace0de19cfcc965Mark Lobodzinski PreCallRecordCmdResolveImage(dev_data, cb_node, src_image_state, dst_image_state); 80006c0400e625554ce7fddb833eeace0de19cfcc965Mark Lobodzinski lock.unlock(); 80014a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdResolveImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, 80024a0754042cf090e131e9e769d8a3633c228625beChris Forbes pRegions); 800309fe5ac5edaec7f0dbcc9fd696e68194569aea89Mark Lobodzinski } 80045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 80055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8006a8d1e377bdeaf61a3209cb997502da4356a185bbMike WeiblenVKAPI_ATTR void VKAPI_CALL GetImageSubresourceLayout(VkDevice device, VkImage image, const VkImageSubresource *pSubresource, 8007a8d1e377bdeaf61a3209cb997502da4356a185bbMike Weiblen VkSubresourceLayout *pLayout) { 8008a8d1e377bdeaf61a3209cb997502da4356a185bbMike Weiblen layer_data *device_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 8009a8d1e377bdeaf61a3209cb997502da4356a185bbMike Weiblen 8010a8d1e377bdeaf61a3209cb997502da4356a185bbMike Weiblen bool skip = PreCallValidateGetImageSubresourceLayout(device_data, image, pSubresource); 8011a8d1e377bdeaf61a3209cb997502da4356a185bbMike Weiblen if (!skip) { 8012b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski device_data->dispatch_table.GetImageSubresourceLayout(device, image, pSubresource, pLayout); 8013b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski } 8014b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski} 8015b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski 8016b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentinebool setEventStageMask(VkQueue queue, VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) { 801756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 80189a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 8019b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine if (pCB) { 8020b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine pCB->eventToStageMap[event] = stageMask; 8021b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine } 8022b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine auto queue_data = dev_data->queueMap.find(queue); 8023b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine if (queue_data != dev_data->queueMap.end()) { 8024b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine queue_data->second.eventToStageMap[event] = stageMask; 8025b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine } 8026b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine return false; 8027b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine} 8028b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine 8029bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) { 803083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 803156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 8032b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 80339a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 80345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 8035baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip_call |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetEvent()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, 8036baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt VALIDATION_ERROR_00237); 803729f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_SETEVENT, "vkCmdSetEvent()"); 80381ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETEVENT); 8039ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen skip_call |= insideRenderPass(dev_data, pCB, "vkCmdSetEvent()", VALIDATION_ERROR_00238); 8040208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis skip_call |= 8041208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis ValidateStageMaskGsTsEnables(dev_data, stageMask, "vkCmdSetEvent()", VALIDATION_ERROR_00230, VALIDATION_ERROR_00231); 80429a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto event_state = GetEventNode(dev_data, event); 80434710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis if (event_state) { 80444710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis addCommandBufferBinding(&event_state->cb_bindings, 8045ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis {reinterpret_cast<uint64_t &>(event), VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT}, pCB); 80464710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis event_state->cb_bindings.insert(pCB); 8047ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis } 80485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->events.push_back(event); 8049c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine if (!pCB->waitedEvents.count(event)) { 8050c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine pCB->writeEventsBeforeWait.push_back(event); 8051c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine } 8052b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine std::function<bool(VkQueue)> eventUpdate = 8053b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine std::bind(setEventStageMask, std::placeholders::_1, commandBuffer, event, stageMask); 8054b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine pCB->eventUpdates.push_back(eventUpdate); 80555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8056b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 8057cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.CmdSetEvent(commandBuffer, event, stageMask); 80585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 80595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8060bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdResetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) { 806183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 806256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 8063b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 80649a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 80655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 8066baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip_call |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdResetEvent()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, 8067baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt VALIDATION_ERROR_00248); 806829f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_RESETEVENT, "vkCmdResetEvent()"); 80691ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_RESETEVENT); 8070ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen skip_call |= insideRenderPass(dev_data, pCB, "vkCmdResetEvent()", VALIDATION_ERROR_00249); 8071208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis skip_call |= 8072208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis ValidateStageMaskGsTsEnables(dev_data, stageMask, "vkCmdResetEvent()", VALIDATION_ERROR_00240, VALIDATION_ERROR_00241); 80739a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto event_state = GetEventNode(dev_data, event); 80744710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis if (event_state) { 80754710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis addCommandBufferBinding(&event_state->cb_bindings, 8076ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis {reinterpret_cast<uint64_t &>(event), VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT}, pCB); 80774710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis event_state->cb_bindings.insert(pCB); 8078ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis } 80795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->events.push_back(event); 8080c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine if (!pCB->waitedEvents.count(event)) { 8081c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine pCB->writeEventsBeforeWait.push_back(event); 8082c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine } 8083208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis // TODO : Add check for VALIDATION_ERROR_00226 8084b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine std::function<bool(VkQueue)> eventUpdate = 8085b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine std::bind(setEventStageMask, std::placeholders::_1, commandBuffer, event, VkPipelineStageFlags(0)); 8086b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine pCB->eventUpdates.push_back(eventUpdate); 80875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8088b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 8089cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.CmdResetEvent(commandBuffer, event, stageMask); 80905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 80915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8092e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool ValidateBarriers(const char *funcName, VkCommandBuffer cmdBuffer, uint32_t memBarrierCount, 8093e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves const VkMemoryBarrier *pMemBarriers, uint32_t bufferBarrierCount, 8094e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves const VkBufferMemoryBarrier *pBufferMemBarriers, uint32_t imageMemBarrierCount, 8095e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves const VkImageMemoryBarrier *pImageMemBarriers) { 8096a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis bool skip = false; 809756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(cmdBuffer), layer_data_map); 80989a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, cmdBuffer); 80995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB->activeRenderPass && memBarrierCount) { 8100ee691f5c5fa87aac3750454d2bca2cb582e4e817Chris Forbes if (!pCB->activeRenderPass->hasSelfDependency[pCB->activeSubpass]) { 8101df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 8102df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(cmdBuffer), __LINE__, DRAWSTATE_INVALID_BARRIER, "DS", 8103cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s: Barriers cannot be set during subpass %d " 8104cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "with no self dependency specified.", 8105a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis funcName, pCB->activeSubpass); 81065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 81075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 81085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < imageMemBarrierCount; ++i) { 81095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto mem_barrier = &pImageMemBarriers[i]; 81109a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_data = GetImageState(dev_data, mem_barrier->image); 81116d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis if (image_data) { 81125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t src_q_f_index = mem_barrier->srcQueueFamilyIndex; 81135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t dst_q_f_index = mem_barrier->dstQueueFamilyIndex; 81146d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis if (image_data->createInfo.sharingMode == VK_SHARING_MODE_CONCURRENT) { 81155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // srcQueueFamilyIndex and dstQueueFamilyIndex must both 81165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // be VK_QUEUE_FAMILY_IGNORED 81175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if ((src_q_f_index != VK_QUEUE_FAMILY_IGNORED) || (dst_q_f_index != VK_QUEUE_FAMILY_IGNORED)) { 8118df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 8119df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t>(cmdBuffer), __LINE__, 8120df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski DRAWSTATE_INVALID_QUEUE_INDEX, "DS", 8121df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "%s: Image Barrier for image 0x%" PRIx64 8122df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski " was created with sharingMode of " 8123df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "VK_SHARING_MODE_CONCURRENT. Src and dst " 8124df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "queueFamilyIndices must be VK_QUEUE_FAMILY_IGNORED.", 8125df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski funcName, reinterpret_cast<const uint64_t &>(mem_barrier->image)); 81265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 81275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 81285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Sharing mode is VK_SHARING_MODE_EXCLUSIVE. srcQueueFamilyIndex and 81295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // dstQueueFamilyIndex must either both be VK_QUEUE_FAMILY_IGNORED, 81305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // or both be a valid queue family 81315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (((src_q_f_index == VK_QUEUE_FAMILY_IGNORED) || (dst_q_f_index == VK_QUEUE_FAMILY_IGNORED)) && 81325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (src_q_f_index != dst_q_f_index)) { 8133df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 8134df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t>(cmdBuffer), __LINE__, 8135df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski DRAWSTATE_INVALID_QUEUE_INDEX, "DS", 8136df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "%s: Image 0x%" PRIx64 8137df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski " was created with sharingMode " 8138df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "of VK_SHARING_MODE_EXCLUSIVE. If one of src- or " 8139df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "dstQueueFamilyIndex is VK_QUEUE_FAMILY_IGNORED, both " 8140df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "must be.", 8141df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski funcName, reinterpret_cast<const uint64_t &>(mem_barrier->image)); 81425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (((src_q_f_index != VK_QUEUE_FAMILY_IGNORED) && (dst_q_f_index != VK_QUEUE_FAMILY_IGNORED)) && 8143b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis ((src_q_f_index >= dev_data->phys_dev_properties.queue_family_properties.size()) || 8144b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis (dst_q_f_index >= dev_data->phys_dev_properties.queue_family_properties.size()))) { 8145df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 8146df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t>(cmdBuffer), __LINE__, 8147df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski DRAWSTATE_INVALID_QUEUE_INDEX, "DS", 8148cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s: Image 0x%" PRIx64 8149cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " was created with sharingMode " 8150a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis "of VK_SHARING_MODE_EXCLUSIVE, but srcQueueFamilyIndex %d" 8151a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis " or dstQueueFamilyIndex %d is greater than " PRINTF_SIZE_T_SPECIFIER 8152a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis "queueFamilies crated for this device.", 8153a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis funcName, reinterpret_cast<const uint64_t &>(mem_barrier->image), src_q_f_index, dst_q_f_index, 8154a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis dev_data->phys_dev_properties.queue_family_properties.size()); 81555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 81565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 81575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 81585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 81595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (mem_barrier) { 8160d678ec4f57d80aa89c24562e9ffe941d8d69e455Tony Barbour if (mem_barrier->oldLayout != mem_barrier->newLayout) { 8161a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis skip |= 8162d678ec4f57d80aa89c24562e9ffe941d8d69e455Tony Barbour ValidateMaskBitsFromLayouts(dev_data, cmdBuffer, mem_barrier->srcAccessMask, mem_barrier->oldLayout, "Source"); 8163a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis skip |= 8164d678ec4f57d80aa89c24562e9ffe941d8d69e455Tony Barbour ValidateMaskBitsFromLayouts(dev_data, cmdBuffer, mem_barrier->dstAccessMask, mem_barrier->newLayout, "Dest"); 8165d678ec4f57d80aa89c24562e9ffe941d8d69e455Tony Barbour } 81665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (mem_barrier->newLayout == VK_IMAGE_LAYOUT_UNDEFINED || mem_barrier->newLayout == VK_IMAGE_LAYOUT_PREINITIALIZED) { 8167df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip |= 8168df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 8169df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(cmdBuffer), __LINE__, DRAWSTATE_INVALID_BARRIER, "DS", 8170df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "%s: Image Layout cannot be transitioned to UNDEFINED or " 8171df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "PREINITIALIZED.", 8172df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski funcName); 81735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 81741d5109d5e0dcc530b27e632e73e1be5e12a28dcdJamie Madill VkFormat format = VK_FORMAT_UNDEFINED; 81751d5109d5e0dcc530b27e632e73e1be5e12a28dcdJamie Madill uint32_t arrayLayers = 0, mipLevels = 0; 81765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool imageFound = false; 81776d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis if (image_data) { 81786d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis format = image_data->createInfo.format; 81796d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis arrayLayers = image_data->createInfo.arrayLayers; 81806d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis mipLevels = image_data->createInfo.mipLevels; 81815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis imageFound = true; 81825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (dev_data->device_extensions.wsi_enabled) { 81839a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto imageswap_data = GetSwapchainFromImage(dev_data, mem_barrier->image); 8184170dc65b45f6bcdec47e02b3aa19435e55b32804Tobin Ehlis if (imageswap_data) { 81859a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto swapchain_data = GetSwapchainNode(dev_data, imageswap_data); 8186b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis if (swapchain_data) { 8187b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis format = swapchain_data->createInfo.imageFormat; 8188b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis arrayLayers = swapchain_data->createInfo.imageArrayLayers; 81895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis mipLevels = 1; 81905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis imageFound = true; 81915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 81925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 81935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 81945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (imageFound) { 8195e08b485346524a30ddfe6526f7dcbbf78c776d10Mark Lobodzinski skip |= ValidateImageSubrangeLevelLayerCounts(dev_data, mem_barrier->subresourceRange, funcName); 8196c37c65e9ff3a0abc86e706ee61d21e1dec882731Tobin Ehlis auto aspect_mask = mem_barrier->subresourceRange.aspectMask; 8197a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis skip |= ValidateImageAspectMask(dev_data, image_data->image, format, aspect_mask, funcName); 819895b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski 819995b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski uint32_t layer_count = ResolveRemainingLayers(&mem_barrier->subresourceRange, image_data->createInfo.arrayLayers); 820095b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski if ((mem_barrier->subresourceRange.baseArrayLayer + layer_count) > arrayLayers) { 8201df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 820295b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t>(cmdBuffer), __LINE__, 820395b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski DRAWSTATE_INVALID_BARRIER, "DS", 820495b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski "%s: Subresource must have the sum of the baseArrayLayer (%d) and layerCount (%d) be less " 8205cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "than or equal to the total number of layers (%d).", 820695b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski funcName, mem_barrier->subresourceRange.baseArrayLayer, layer_count, arrayLayers); 82075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 820895b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski 820995b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski uint32_t level_count = ResolveRemainingLevels(&mem_barrier->subresourceRange, image_data->createInfo.mipLevels); 821095b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski if ((mem_barrier->subresourceRange.baseMipLevel + level_count) > mipLevels) { 8211df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip |= log_msg( 8212df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 8213df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(cmdBuffer), __LINE__, DRAWSTATE_INVALID_BARRIER, "DS", 821495b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski "%s: Subresource must have the sum of the baseMipLevel (%d) and levelCount (%d) be less than or equal to " 8215df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "the total number of levels (%d).", 821695b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski funcName, mem_barrier->subresourceRange.baseMipLevel, level_count, mipLevels); 82175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 82185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 82195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 82205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 82215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < bufferBarrierCount; ++i) { 82225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto mem_barrier = &pBufferMemBarriers[i]; 82235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB->activeRenderPass) { 8224df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 8225df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(cmdBuffer), __LINE__, DRAWSTATE_INVALID_BARRIER, "DS", 8226df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "%s: Buffer Barriers cannot be used during a render pass.", funcName); 82275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8228cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!mem_barrier) continue; 82295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 82305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Validate buffer barrier queue family indices 82315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if ((mem_barrier->srcQueueFamilyIndex != VK_QUEUE_FAMILY_IGNORED && 8232b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis mem_barrier->srcQueueFamilyIndex >= dev_data->phys_dev_properties.queue_family_properties.size()) || 82335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (mem_barrier->dstQueueFamilyIndex != VK_QUEUE_FAMILY_IGNORED && 8234b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis mem_barrier->dstQueueFamilyIndex >= dev_data->phys_dev_properties.queue_family_properties.size())) { 8235df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 8236df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(cmdBuffer), __LINE__, DRAWSTATE_INVALID_QUEUE_INDEX, "DS", 8237cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s: Buffer Barrier 0x%" PRIx64 8238cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " has QueueFamilyIndex greater " 8239a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis "than the number of QueueFamilies (" PRINTF_SIZE_T_SPECIFIER ") for this device.", 8240a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis funcName, reinterpret_cast<const uint64_t &>(mem_barrier->buffer), 8241a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis dev_data->phys_dev_properties.queue_family_properties.size()); 82425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 82435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 82449a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto buffer_state = GetBufferState(dev_data, mem_barrier->buffer); 82455cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis if (buffer_state) { 82465cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis auto buffer_size = buffer_state->requirements.size; 82475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (mem_barrier->offset >= buffer_size) { 8248a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis skip |= log_msg( 8249df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 8250df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(cmdBuffer), __LINE__, DRAWSTATE_INVALID_BARRIER, "DS", 8251df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "%s: Buffer Barrier 0x%" PRIx64 " has offset 0x%" PRIx64 " which is not less than total size 0x%" PRIx64 ".", 825294c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis funcName, reinterpret_cast<const uint64_t &>(mem_barrier->buffer), 8253df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<const uint64_t &>(mem_barrier->offset), reinterpret_cast<const uint64_t &>(buffer_size)); 8254df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski } else if (mem_barrier->size != VK_WHOLE_SIZE && (mem_barrier->offset + mem_barrier->size > buffer_size)) { 8255df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip |= 8256df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 8257df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(cmdBuffer), __LINE__, DRAWSTATE_INVALID_BARRIER, "DS", 8258df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "%s: Buffer Barrier 0x%" PRIx64 " has offset 0x%" PRIx64 " and size 0x%" PRIx64 8259df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski " whose sum is greater than total size 0x%" PRIx64 ".", 8260df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski funcName, reinterpret_cast<const uint64_t &>(mem_barrier->buffer), 8261df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<const uint64_t &>(mem_barrier->offset), 8262df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<const uint64_t &>(mem_barrier->size), reinterpret_cast<const uint64_t &>(buffer_size)); 82635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 82645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 82655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8266a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis return skip; 82675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 82685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8269bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskibool validateEventStageMask(VkQueue queue, GLOBAL_CB_NODE *pCB, uint32_t eventCount, size_t firstEventIndex, 8270bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkPipelineStageFlags sourceStageMask) { 8271b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine bool skip_call = false; 8272b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine VkPipelineStageFlags stageMask = 0; 827356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map); 8274b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine for (uint32_t i = 0; i < eventCount; ++i) { 82752ab14387df9b890fe4b13494ea249dd03cf898d2Chris Forbes auto event = pCB->events[firstEventIndex + i]; 8276b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine auto queue_data = dev_data->queueMap.find(queue); 8277cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (queue_data == dev_data->queueMap.end()) return false; 82782ab14387df9b890fe4b13494ea249dd03cf898d2Chris Forbes auto event_data = queue_data->second.eventToStageMap.find(event); 8279b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine if (event_data != queue_data->second.eventToStageMap.end()) { 8280b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine stageMask |= event_data->second; 8281b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine } else { 82829a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto global_event_data = GetEventNode(dev_data, event); 82839556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis if (!global_event_data) { 8284b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT, 828527c3e0dda9e30d1d334728bbd373e8d7011257d4Chris Forbes reinterpret_cast<const uint64_t &>(event), __LINE__, DRAWSTATE_INVALID_EVENT, "DS", 828627c3e0dda9e30d1d334728bbd373e8d7011257d4Chris Forbes "Event 0x%" PRIx64 " cannot be waited on if it has never been set.", 82872ab14387df9b890fe4b13494ea249dd03cf898d2Chris Forbes reinterpret_cast<const uint64_t &>(event)); 8288b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine } else { 82899556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis stageMask |= global_event_data->stageMask; 8290b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine } 8291b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine } 8292b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine } 8293c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine // TODO: Need to validate that host_bit is only set if set event is called 8294c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine // but set event can be called at any time. 8295c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine if (sourceStageMask != stageMask && sourceStageMask != (stageMask | VK_PIPELINE_STAGE_HOST_BIT)) { 8296df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 8297df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(pCB->commandBuffer), __LINE__, VALIDATION_ERROR_00254, "DS", 8298cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Submitting cmdbuffer with call to VkCmdWaitEvents " 8299cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "using srcStageMask 0x%X which must be the bitwise " 8300cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "OR of the stageMask parameters used in calls to " 8301cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkCmdSetEvent and VK_PIPELINE_STAGE_HOST_BIT if " 8302cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "used with vkSetEvent but instead is 0x%X. %s", 83039bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt sourceStageMask, stageMask, validation_error_map[VALIDATION_ERROR_00254]); 8304b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine } 8305b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine return skip_call; 8306b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine} 8307b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine 830807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski// Note that we only check bits that HAVE required queueflags -- don't care entries are skipped 830907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinskistatic std::unordered_map<VkPipelineStageFlags, VkQueueFlags> supported_pipeline_stages_table = { 831007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX, VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT}, 831107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT}, 831207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_QUEUE_GRAPHICS_BIT}, 831307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, VK_QUEUE_GRAPHICS_BIT}, 831407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT, VK_QUEUE_GRAPHICS_BIT}, 831507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT, VK_QUEUE_GRAPHICS_BIT}, 831607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT, VK_QUEUE_GRAPHICS_BIT}, 831707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_QUEUE_GRAPHICS_BIT}, 831807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, VK_QUEUE_GRAPHICS_BIT}, 831907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_QUEUE_GRAPHICS_BIT}, 832007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_QUEUE_GRAPHICS_BIT}, 832107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_QUEUE_COMPUTE_BIT}, 832207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_TRANSFER_BIT, VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT}, 832307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_QUEUE_GRAPHICS_BIT}}; 832407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski 832507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinskistatic const VkPipelineStageFlags stage_flag_bit_array[] = {VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX, 832607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, 832707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 832807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, 832907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT, 833007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT, 833107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT, 833207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 833307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, 833407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, 833507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 833607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 833707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_TRANSFER_BIT, 833807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT}; 833907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski 834007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinskibool CheckStageMaskQueueCompatibility(layer_data *dev_data, VkCommandBuffer command_buffer, VkPipelineStageFlags stage_mask, 834107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VkQueueFlags queue_flags, const char *function, const char *src_or_dest, 834207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski UNIQUE_VALIDATION_ERROR_CODE error_code) { 834307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski bool skip = false; 834407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski // Lookup each bit in the stagemask and check for overlap between its table bits and queue_flags 834507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski for (const auto &item : stage_flag_bit_array) { 834607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski if (stage_mask & item) { 834707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski if ((supported_pipeline_stages_table[item] & queue_flags) == 0) { 834807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski skip |= 834907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 835007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski reinterpret_cast<uint64_t &>(command_buffer), __LINE__, error_code, "DL", 835107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski "%s(): %s flag %s is not compatible with the queue family properties of this " 835207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski "command buffer. %s", 835307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski function, src_or_dest, string_VkPipelineStageFlagBits(static_cast<VkPipelineStageFlagBits>(item)), 835407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski validation_error_map[error_code]); 835507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski } 835607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski } 835707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski } 835807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski return skip; 835907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski} 836007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski 836107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinskibool ValidateStageMasksAgainstQueueCapabilities(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, 836207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VkPipelineStageFlags source_stage_mask, VkPipelineStageFlags dest_stage_mask, 836307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski const char *function, UNIQUE_VALIDATION_ERROR_CODE error_code) { 836407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski bool skip = false; 836507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski uint32_t queue_family_index = dev_data->commandPoolMap[cb_state->createInfo.commandPool].queueFamilyIndex; 836656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(dev_data->physical_device), instance_layer_data_map); 83679a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto physical_device_state = GetPhysicalDeviceState(instance_data, dev_data->physical_device); 836807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski 836907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski // Any pipeline stage included in srcStageMask or dstStageMask must be supported by the capabilities of the queue family 837007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski // specified by the queueFamilyIndex member of the VkCommandPoolCreateInfo structure that was used to create the VkCommandPool 837107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski // that commandBuffer was allocated from, as specified in the table of supported pipeline stages. 837207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski 837307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski if (queue_family_index < physical_device_state->queue_family_properties.size()) { 837407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VkQueueFlags specified_queue_flags = physical_device_state->queue_family_properties[queue_family_index].queueFlags; 837507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski 837607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski if ((source_stage_mask & VK_PIPELINE_STAGE_ALL_COMMANDS_BIT) == 0) { 837707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski skip |= CheckStageMaskQueueCompatibility(dev_data, cb_state->commandBuffer, source_stage_mask, specified_queue_flags, 837807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski function, "srcStageMask", error_code); 837907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski } 838007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski if ((dest_stage_mask & VK_PIPELINE_STAGE_ALL_COMMANDS_BIT) == 0) { 838107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski skip |= CheckStageMaskQueueCompatibility(dev_data, cb_state->commandBuffer, dest_stage_mask, specified_queue_flags, 838207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski function, "dstStageMask", error_code); 838307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski } 838407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski } 838507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski return skip; 838607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski} 838707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski 8388d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent *pEvents, 8389d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski VkPipelineStageFlags sourceStageMask, VkPipelineStageFlags dstStageMask, 8390d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers, 8391d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers, 8392d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers) { 8393d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski bool skip = false; 839456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 8395b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 83969a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer); 8397d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski if (cb_state) { 8398d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski skip |= ValidateStageMasksAgainstQueueCapabilities(dev_data, cb_state, sourceStageMask, dstStageMask, "vkCmdWaitEvents", 8399d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski VALIDATION_ERROR_02510); 8400208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis skip |= ValidateStageMaskGsTsEnables(dev_data, sourceStageMask, "vkCmdWaitEvents()", VALIDATION_ERROR_02067, 8401208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis VALIDATION_ERROR_02069); 8402208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis skip |= ValidateStageMaskGsTsEnables(dev_data, dstStageMask, "vkCmdWaitEvents()", VALIDATION_ERROR_02068, 8403208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis VALIDATION_ERROR_02070); 8404d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski auto first_event_index = cb_state->events.size(); 84055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < eventCount; ++i) { 84069a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto event_state = GetEventNode(dev_data, pEvents[i]); 84074710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis if (event_state) { 84084710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis addCommandBufferBinding(&event_state->cb_bindings, 8409ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis {reinterpret_cast<const uint64_t &>(pEvents[i]), VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT}, 8410d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski cb_state); 8411d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski event_state->cb_bindings.insert(cb_state); 8412ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis } 8413d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski cb_state->waitedEvents.insert(pEvents[i]); 8414d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski cb_state->events.push_back(pEvents[i]); 84155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8416d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski std::function<bool(VkQueue)> event_update = 8417d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski std::bind(validateEventStageMask, std::placeholders::_1, cb_state, eventCount, first_event_index, sourceStageMask); 8418d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski cb_state->eventUpdates.push_back(event_update); 8419baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip |= ValidateCmdQueueFlags(dev_data, cb_state, "vkCmdWaitEvents()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, 8420baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt VALIDATION_ERROR_00262); 8421ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski skip |= ValidateCmd(dev_data, cb_state, CMD_WAITEVENTS, "vkCmdWaitEvents()"); 8422ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski UpdateCmdBufferLastCmd(cb_state, CMD_WAITEVENTS); 8423a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen skip |= 8424a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen ValidateBarriersToImages(dev_data, commandBuffer, imageMemoryBarrierCount, pImageMemoryBarriers, "vkCmdWaitEvents()"); 8425e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski if (!skip) { 8426e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski TransitionImageLayouts(dev_data, commandBuffer, imageMemoryBarrierCount, pImageMemoryBarriers); 8427e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski } 8428e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski 8429364a03b109f0b2b37be2e13d293fa93b8af5203aMike Weiblen skip |= ValidateBarriers("vkCmdWaitEvents()", commandBuffer, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, 8430d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers); 84315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8432b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 8433d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski if (!skip) 84344a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdWaitEvents(commandBuffer, eventCount, pEvents, sourceStageMask, dstStageMask, 84354a0754042cf090e131e9e769d8a3633c228625beChris Forbes memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, 84364a0754042cf090e131e9e769d8a3633c228625beChris Forbes imageMemoryBarrierCount, pImageMemoryBarriers); 84375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 84385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 843903122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinskistatic bool PreCallValidateCmdPipelineBarrier(layer_data *device_data, GLOBAL_CB_NODE *cb_state, VkCommandBuffer commandBuffer, 844003122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, 844103122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers, 844203122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers, 844303122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers) { 844403122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski bool skip = false; 844503122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski skip |= ValidateStageMasksAgainstQueueCapabilities(device_data, cb_state, srcStageMask, dstStageMask, "vkCmdPipelineBarrier", 844603122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski VALIDATION_ERROR_02513); 8447baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip |= ValidateCmdQueueFlags(device_data, cb_state, "vkCmdPipelineBarrier()", 8448baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt VK_QUEUE_TRANSFER_BIT | VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, VALIDATION_ERROR_00280); 844903122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski skip |= ValidateCmd(device_data, cb_state, CMD_PIPELINEBARRIER, "vkCmdPipelineBarrier()"); 845003122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski skip |= ValidateStageMaskGsTsEnables(device_data, srcStageMask, "vkCmdPipelineBarrier()", VALIDATION_ERROR_00265, 845103122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski VALIDATION_ERROR_00267); 845203122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski skip |= ValidateStageMaskGsTsEnables(device_data, dstStageMask, "vkCmdPipelineBarrier()", VALIDATION_ERROR_00266, 845303122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski VALIDATION_ERROR_00268); 8454a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen skip |= ValidateBarriersToImages(device_data, commandBuffer, imageMemoryBarrierCount, pImageMemoryBarriers, 8455a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen "vkCmdPipelineBarrier()"); 845603122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski skip |= ValidateBarriers("vkCmdPipelineBarrier()", commandBuffer, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, 845703122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers); 845803122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski return skip; 845903122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski} 846003122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski 84616f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinskistatic void PreCallRecordCmdPipelineBarrier(layer_data *device_data, GLOBAL_CB_NODE *cb_state, VkCommandBuffer commandBuffer, 84626f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers) { 84636f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski UpdateCmdBufferLastCmd(cb_state, CMD_PIPELINEBARRIER); 84646f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski TransitionImageLayouts(device_data, commandBuffer, imageMemoryBarrierCount, pImageMemoryBarriers); 84656f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski} 84666f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski 8467d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdPipelineBarrier(VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask, 8468d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags, 8469d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers, 8470d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers, 8471d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers) { 8472d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski bool skip = false; 84736f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 8474b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 84756f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski GLOBAL_CB_NODE *cb_state = GetCBNode(device_data, commandBuffer); 8476d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski if (cb_state) { 84776f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski skip |= PreCallValidateCmdPipelineBarrier(device_data, cb_state, commandBuffer, srcStageMask, dstStageMask, 847803122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, 847903122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers); 84806f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski if (!skip) { 84816f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski PreCallRecordCmdPipelineBarrier(device_data, cb_state, commandBuffer, imageMemoryBarrierCount, pImageMemoryBarriers); 84826f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski } 84836f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski } else { 84846f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski assert(0); 84855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8486b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 8487a79957f762f6fc6b74c25cb94d35a3fc36967471Tony Barbour if (!skip) { 8488a79957f762f6fc6b74c25cb94d35a3fc36967471Tony Barbour device_data->dispatch_table.CmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, memoryBarrierCount, 8489a79957f762f6fc6b74c25cb94d35a3fc36967471Tony Barbour pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, 8490a79957f762f6fc6b74c25cb94d35a3fc36967471Tony Barbour imageMemoryBarrierCount, pImageMemoryBarriers); 8491a79957f762f6fc6b74c25cb94d35a3fc36967471Tony Barbour } 84925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 84935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8494d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentinebool setQueryState(VkQueue queue, VkCommandBuffer commandBuffer, QueryObject object, bool value) { 849556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 84969a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 8497d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine if (pCB) { 8498d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine pCB->queryToStateMap[object] = value; 8499d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 8500d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine auto queue_data = dev_data->queueMap.find(queue); 8501d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine if (queue_data != dev_data->queueMap.end()) { 8502d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine queue_data->second.queryToStateMap[object] = value; 8503d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 8504d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine return false; 8505d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine} 8506d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine 8507bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBeginQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t slot, VkFlags flags) { 850883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 850956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 8510b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 85119a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 85125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 85135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis QueryObject query = {queryPool, slot}; 85145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->activeQueries.insert(query); 85155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!pCB->startedQueries.count(query)) { 85165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->startedQueries.insert(query); 85175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8518baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip_call |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdBeginQuery()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, 8519baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt VALIDATION_ERROR_01039); 852029f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_BEGINQUERY, "vkCmdBeginQuery()"); 85211ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_BEGINQUERY); 85229a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis addCommandBufferBinding(&GetQueryPoolNode(dev_data, queryPool)->cb_bindings, 8523ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis {reinterpret_cast<uint64_t &>(queryPool), VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT}, pCB); 85245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8525b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 8526cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.CmdBeginQuery(commandBuffer, queryPool, slot, flags); 85275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 85285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 852989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdEndQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t slot) { 8530946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski bool skip = false; 853156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 8532b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 8533946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer); 8534946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (cb_state) { 85355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis QueryObject query = {queryPool, slot}; 8536946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (!cb_state->activeQueries.count(query)) { 8537df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 8538df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(commandBuffer), __LINE__, VALIDATION_ERROR_01041, "DS", 8539df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "Ending a query before it was started: queryPool 0x%" PRIx64 ", index %d. %s", (uint64_t)(queryPool), 8540df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski slot, validation_error_map[VALIDATION_ERROR_01041]); 85415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 8542946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->activeQueries.erase(query); 85435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8544946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski std::function<bool(VkQueue)> query_update = std::bind(setQueryState, std::placeholders::_1, commandBuffer, query, true); 8545946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->queryUpdates.push_back(query_update); 8546baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip |= ValidateCmdQueueFlags(dev_data, cb_state, "VkCmdEndQuery()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, 8547baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt VALIDATION_ERROR_01046); 8548946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ValidateCmd(dev_data, cb_state, CMD_ENDQUERY, "VkCmdEndQuery()"); 8549946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski UpdateCmdBufferLastCmd(cb_state, CMD_ENDQUERY); 85509a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis addCommandBufferBinding(&GetQueryPoolNode(dev_data, queryPool)->cb_bindings, 8551946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski {reinterpret_cast<uint64_t &>(queryPool), VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT}, cb_state); 85525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8553b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 8554946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdEndQuery(commandBuffer, queryPool, slot); 85555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 85565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8557bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdResetQueryPool(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, 8558bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski uint32_t queryCount) { 8559946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski bool skip = false; 856056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 8561b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 8562946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer); 8563946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (cb_state) { 85645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < queryCount; i++) { 85655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis QueryObject query = {queryPool, firstQuery + i}; 8566946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->waitedEventsBeforeQueryReset[query] = cb_state->waitedEvents; 8567946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski std::function<bool(VkQueue)> query_update = 8568946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski std::bind(setQueryState, std::placeholders::_1, commandBuffer, query, false); 8569946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->queryUpdates.push_back(query_update); 8570946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski } 8571baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip |= ValidateCmdQueueFlags(dev_data, cb_state, "VkCmdResetQueryPool()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, 8572baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt VALIDATION_ERROR_01024); 8573946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ValidateCmd(dev_data, cb_state, CMD_RESETQUERYPOOL, "VkCmdResetQueryPool()"); 8574946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski UpdateCmdBufferLastCmd(cb_state, CMD_RESETQUERYPOOL); 8575946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= insideRenderPass(dev_data, cb_state, "vkCmdResetQueryPool()", VALIDATION_ERROR_01025); 85769a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis addCommandBufferBinding(&GetQueryPoolNode(dev_data, queryPool)->cb_bindings, 8577946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski {reinterpret_cast<uint64_t &>(queryPool), VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT}, cb_state); 85785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8579b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 8580946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdResetQueryPool(commandBuffer, queryPool, firstQuery, queryCount); 85815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 85825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8583d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentinebool validateQuery(VkQueue queue, GLOBAL_CB_NODE *pCB, VkQueryPool queryPool, uint32_t queryCount, uint32_t firstQuery) { 8584d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine bool skip_call = false; 858556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(pCB->commandBuffer), layer_data_map); 8586d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine auto queue_data = dev_data->queueMap.find(queue); 8587cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (queue_data == dev_data->queueMap.end()) return false; 8588d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine for (uint32_t i = 0; i < queryCount; i++) { 8589d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine QueryObject query = {queryPool, firstQuery + i}; 8590d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine auto query_data = queue_data->second.queryToStateMap.find(query); 8591d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine bool fail = false; 8592d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine if (query_data != queue_data->second.queryToStateMap.end()) { 8593d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine if (!query_data->second) { 8594d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine fail = true; 8595d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 8596d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } else { 8597d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine auto global_query_data = dev_data->queryToStateMap.find(query); 8598d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine if (global_query_data != dev_data->queryToStateMap.end()) { 8599d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine if (!global_query_data->second) { 8600d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine fail = true; 8601d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 8602d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } else { 8603d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine fail = true; 8604d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 8605d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 8606d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine if (fail) { 8607df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= 8608df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 8609df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_QUERY, "DS", 8610df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "Requesting a copy from query to buffer with invalid query: queryPool 0x%" PRIx64 ", index %d", 8611df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t &>(queryPool), firstQuery + i); 8612d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 8613d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 8614d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine return skip_call; 8615d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine} 8616d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine 8617bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdCopyQueryPoolResults(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, 8618bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski uint32_t queryCount, VkBuffer dstBuffer, VkDeviceSize dstOffset, 8619bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDeviceSize stride, VkQueryResultFlags flags) { 8620946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski bool skip = false; 862156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 8622b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 8623ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis 86249a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, commandBuffer); 86259a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto dst_buff_state = GetBufferState(dev_data, dstBuffer); 86265cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis if (cb_node && dst_buff_state) { 8627946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ValidateMemoryIsBoundToBuffer(dev_data, dst_buff_state, "vkCmdCopyQueryPoolResults()", VALIDATION_ERROR_02526); 8628ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis // Update bindings between buffer and cmd buffer 86295cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis AddCommandBufferBindingBuffer(dev_data, cb_node, dst_buff_state); 8630ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis // Validate that DST buffer has correct usage flags set 8631946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ValidateBufferUsageFlags(dev_data, dst_buff_state, VK_BUFFER_USAGE_TRANSFER_DST_BIT, true, VALIDATION_ERROR_01066, 8632946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "vkCmdCopyQueryPoolResults()", "VK_BUFFER_USAGE_TRANSFER_DST_BIT"); 8633e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves std::function<bool()> function = [=]() { 86345cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis SetBufferMemoryValid(dev_data, dst_buff_state, true); 8635e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves return false; 86365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis }; 86379f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis cb_node->validate_functions.push_back(function); 8638946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski std::function<bool(VkQueue)> query_update = 8639ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis std::bind(validateQuery, std::placeholders::_1, cb_node, queryPool, queryCount, firstQuery); 8640946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_node->queryUpdates.push_back(query_update); 8641baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip |= ValidateCmdQueueFlags(dev_data, cb_node, "vkCmdCopyQueryPoolResults()", 8642baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, VALIDATION_ERROR_01073); 8643946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ValidateCmd(dev_data, cb_node, CMD_COPYQUERYPOOLRESULTS, "vkCmdCopyQueryPoolResults()"); 8644ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski UpdateCmdBufferLastCmd(cb_node, CMD_COPYQUERYPOOLRESULTS); 8645946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= insideRenderPass(dev_data, cb_node, "vkCmdCopyQueryPoolResults()", VALIDATION_ERROR_01074); 86469a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis addCommandBufferBinding(&GetQueryPoolNode(dev_data, queryPool)->cb_bindings, 8647ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis {reinterpret_cast<uint64_t &>(queryPool), VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT}, cb_node); 8648ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } else { 8649ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis assert(0); 86505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8651b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 8652946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (!skip) 86534a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdCopyQueryPoolResults(commandBuffer, queryPool, firstQuery, queryCount, dstBuffer, dstOffset, 86544a0754042cf090e131e9e769d8a3633c228625beChris Forbes stride, flags); 86555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 86565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8657bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdPushConstants(VkCommandBuffer commandBuffer, VkPipelineLayout layout, VkShaderStageFlags stageFlags, 8658bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski uint32_t offset, uint32_t size, const void *pValues) { 8659946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski bool skip = false; 866056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 8661b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 8662946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer); 8663946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (cb_state) { 8664baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip |= ValidateCmdQueueFlags(dev_data, cb_state, "vkCmdPushConstants()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, 8665baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt VALIDATION_ERROR_00999); 8666946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ValidateCmd(dev_data, cb_state, CMD_PUSHCONSTANTS, "vkCmdPushConstants()"); 8667946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski UpdateCmdBufferLastCmd(cb_state, CMD_PUSHCONSTANTS); 86685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8669946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= validatePushConstantRange(dev_data, offset, size, "vkCmdPushConstants()"); 86709e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz if (0 == stageFlags) { 8671df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 8672df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(commandBuffer), __LINE__, VALIDATION_ERROR_00996, "DS", 8673df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "vkCmdPushConstants() call has no stageFlags set. %s", validation_error_map[VALIDATION_ERROR_00996]); 86749e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 86759e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz 8676bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz // Check if specified push constant range falls within a pipeline-defined range which has matching stageFlags. 8677bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz // The spec doesn't seem to disallow having multiple push constant ranges with the 8678bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz // same offset and size, but different stageFlags. So we can't just check the 8679bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz // stageFlags in the first range with matching offset and size. 8680bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz if (!skip) { 8681bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz const auto &ranges = getPipelineLayout(dev_data, layout)->push_constant_ranges; 8682bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz bool found_matching_range = false; 8683bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz for (const auto &range : ranges) { 8684bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz if ((stageFlags == range.stageFlags) && (offset >= range.offset) && (offset + size <= range.offset + range.size)) { 8685bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz found_matching_range = true; 868615a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis break; 8687a95cb74c9d0947ab3821b15e1289755286ea78eeKarl Schultz } 86889e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 8689bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz if (!found_matching_range) { 8690df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 8691df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(commandBuffer), __LINE__, VALIDATION_ERROR_00988, "DS", 8692df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "vkCmdPushConstants() stageFlags = 0x%" PRIx32 8693df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski " do not match the stageFlags in any of the ranges with" 8694df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski " offset = %d and size = %d in pipeline layout 0x%" PRIx64 ". %s", 8695bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz (uint32_t)stageFlags, offset, size, (uint64_t)layout, validation_error_map[VALIDATION_ERROR_00988]); 869615a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis } 86975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8698b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 8699946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdPushConstants(commandBuffer, layout, stageFlags, offset, size, pValues); 87005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 87015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8702bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdWriteTimestamp(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, 8703bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkQueryPool queryPool, uint32_t slot) { 8704946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski bool skip = false; 870556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 8706b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 8707946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer); 8708946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (cb_state) { 87095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis QueryObject query = {queryPool, slot}; 8710946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski std::function<bool(VkQueue)> query_update = std::bind(setQueryState, std::placeholders::_1, commandBuffer, query, true); 8711946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->queryUpdates.push_back(query_update); 8712baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip |= ValidateCmdQueueFlags(dev_data, cb_state, "vkCmdWriteTimestamp()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, 8713baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt VALIDATION_ERROR_01082); 8714946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ValidateCmd(dev_data, cb_state, CMD_WRITETIMESTAMP, "vkCmdWriteTimestamp()"); 8715946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski UpdateCmdBufferLastCmd(cb_state, CMD_WRITETIMESTAMP); 87165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8717b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 8718946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdWriteTimestamp(commandBuffer, pipelineStage, queryPool, slot); 87195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 87205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 87216600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinskistatic bool MatchUsage(layer_data *dev_data, uint32_t count, const VkAttachmentReference *attachments, 87229bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt const VkFramebufferCreateInfo *fbci, VkImageUsageFlagBits usage_flag, 87239bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt UNIQUE_VALIDATION_ERROR_CODE error_code) { 8724946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski bool skip = false; 87256600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski 87266600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski for (uint32_t attach = 0; attach < count; attach++) { 87276600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski if (attachments[attach].attachment != VK_ATTACHMENT_UNUSED) { 87286600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski // Attachment counts are verified elsewhere, but prevent an invalid access 87296600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski if (attachments[attach].attachment < fbci->attachmentCount) { 87306600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski const VkImageView *image_view = &fbci->pAttachments[attachments[attach].attachment]; 87319a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto view_state = GetImageViewState(dev_data, *image_view); 873279fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis if (view_state) { 87339a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis const VkImageCreateInfo *ici = &GetImageState(dev_data, view_state->create_info.image)->createInfo; 87346600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski if (ici != nullptr) { 87356600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski if ((ici->usage & usage_flag) == 0) { 8736df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 8737df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, error_code, "DS", 8738946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "vkCreateFramebuffer: Framebuffer Attachment (%d) conflicts with the image's " 8739946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "IMAGE_USAGE flags (%s). %s", 8740946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski attachments[attach].attachment, string_VkImageUsageFlagBits(usage_flag), 8741946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski validation_error_map[error_code]); 87426600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski } 87436600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski } 87446600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski } 87456600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski } 87466600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski } 87476600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski } 8748946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski return skip; 87496600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski} 87506600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski 8751d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis// Validate VkFramebufferCreateInfo which includes: 8752d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis// 1. attachmentCount equals renderPass attachmentCount 87535ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 2. corresponding framebuffer and renderpass attachments have matching formats 87545ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 3. corresponding framebuffer and renderpass attachments have matching sample counts 87555ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 4. fb attachments only have a single mip level 87565ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 5. fb attachment dimensions are each at least as large as the fb 87575ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 6. fb attachments use idenity swizzle 87585ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 7. fb attachments used by renderPass for color/input/ds have correct usage bit set 87596fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis// 8. fb dimensions are within physical device limits 8760d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlisstatic bool ValidateFramebufferCreateInfo(layer_data *dev_data, const VkFramebufferCreateInfo *pCreateInfo) { 87616600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski bool skip_call = false; 87626600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski 87639a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto rp_state = GetRenderPassState(dev_data, pCreateInfo->renderPass); 8764127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis if (rp_state) { 8765127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis const VkRenderPassCreateInfo *rpci = rp_state->createInfo.ptr(); 8766d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis if (rpci->attachmentCount != pCreateInfo->attachmentCount) { 8767d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis skip_call |= log_msg( 8768d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT, 87699bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt reinterpret_cast<const uint64_t &>(pCreateInfo->renderPass), __LINE__, VALIDATION_ERROR_00404, "DS", 8770d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis "vkCreateFramebuffer(): VkFramebufferCreateInfo attachmentCount of %u does not match attachmentCount of %u of " 87719bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "renderPass (0x%" PRIxLEAST64 ") being used to create Framebuffer. %s", 87729bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt pCreateInfo->attachmentCount, rpci->attachmentCount, reinterpret_cast<const uint64_t &>(pCreateInfo->renderPass), 87739bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt validation_error_map[VALIDATION_ERROR_00404]); 87745ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis } else { 877541ebcb6b517b1de5ae456d46d866f5e84a96a2c5Tobin Ehlis // attachmentCounts match, so make sure corresponding attachment details line up 87765ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis const VkImageView *image_views = pCreateInfo->pAttachments; 87775ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) { 87789a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto view_state = GetImageViewState(dev_data, image_views[i]); 877912d5600c2f9e32343016fd944432ba95df370797Tobin Ehlis auto &ivci = view_state->create_info; 878079fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis if (ivci.format != rpci->pAttachments[i].format) { 87815ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis skip_call |= log_msg( 87825ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT, 87839bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt reinterpret_cast<const uint64_t &>(pCreateInfo->renderPass), __LINE__, VALIDATION_ERROR_00408, "DS", 87849bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "vkCreateFramebuffer(): VkFramebufferCreateInfo attachment #%u has format of %s that does not match " 87859bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "the format of " 87869bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "%s used by the corresponding attachment for renderPass (0x%" PRIxLEAST64 "). %s", 878779fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis i, string_VkFormat(ivci.format), string_VkFormat(rpci->pAttachments[i].format), 87889bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt reinterpret_cast<const uint64_t &>(pCreateInfo->renderPass), validation_error_map[VALIDATION_ERROR_00408]); 87895ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis } 87909a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis const VkImageCreateInfo *ici = &GetImageState(dev_data, ivci.image)->createInfo; 87915ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis if (ici->samples != rpci->pAttachments[i].samples) { 879241ebcb6b517b1de5ae456d46d866f5e84a96a2c5Tobin Ehlis skip_call |= log_msg( 879341ebcb6b517b1de5ae456d46d866f5e84a96a2c5Tobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT, 87949bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt reinterpret_cast<const uint64_t &>(pCreateInfo->renderPass), __LINE__, VALIDATION_ERROR_00409, "DS", 87959bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "vkCreateFramebuffer(): VkFramebufferCreateInfo attachment #%u has %s samples that do not match " 87969bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "the %s samples used by the corresponding attachment for renderPass (0x%" PRIxLEAST64 "). %s", 879741ebcb6b517b1de5ae456d46d866f5e84a96a2c5Tobin Ehlis i, string_VkSampleCountFlagBits(ici->samples), string_VkSampleCountFlagBits(rpci->pAttachments[i].samples), 87989bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt reinterpret_cast<const uint64_t &>(pCreateInfo->renderPass), validation_error_map[VALIDATION_ERROR_00409]); 87995ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis } 88005ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis // Verify that view only has a single mip level 880179fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis if (ivci.subresourceRange.levelCount != 1) { 88029bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt skip_call |= 88039bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 88049bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt VALIDATION_ERROR_00411, "DS", 88059bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "vkCreateFramebuffer(): VkFramebufferCreateInfo attachment #%u has mip levelCount of %u " 88069bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "but only a single mip level (levelCount == 1) is allowed when creating a Framebuffer. %s", 88079bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt i, ivci.subresourceRange.levelCount, validation_error_map[VALIDATION_ERROR_00411]); 88085ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis } 880979fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis const uint32_t mip_level = ivci.subresourceRange.baseMipLevel; 8810aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis uint32_t mip_width = max(1u, ici->extent.width >> mip_level); 8811aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis uint32_t mip_height = max(1u, ici->extent.height >> mip_level); 881279fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis if ((ivci.subresourceRange.layerCount < pCreateInfo->layers) || (mip_width < pCreateInfo->width) || 8813aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis (mip_height < pCreateInfo->height)) { 8814aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis skip_call |= 88156fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 8816aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis DRAWSTATE_INVALID_FRAMEBUFFER_CREATE_INFO, "DS", 8817aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis "vkCreateFramebuffer(): VkFramebufferCreateInfo attachment #%u mip level %u has dimensions smaller " 8818aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis "than the corresponding " 8819aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis "framebuffer dimensions. Attachment dimensions must be at least as large. Here are the respective " 8820aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis "dimensions for " 8821aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis "attachment #%u, framebuffer:\n" 8822aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis "width: %u, %u\n" 8823aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis "height: %u, %u\n" 8824aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis "layerCount: %u, %u\n", 882579fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis i, ivci.subresourceRange.baseMipLevel, i, mip_width, pCreateInfo->width, mip_height, 882679fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis pCreateInfo->height, ivci.subresourceRange.layerCount, pCreateInfo->layers); 88275ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis } 882879fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis if (((ivci.components.r != VK_COMPONENT_SWIZZLE_IDENTITY) && (ivci.components.r != VK_COMPONENT_SWIZZLE_R)) || 882979fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis ((ivci.components.g != VK_COMPONENT_SWIZZLE_IDENTITY) && (ivci.components.g != VK_COMPONENT_SWIZZLE_G)) || 883079fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis ((ivci.components.b != VK_COMPONENT_SWIZZLE_IDENTITY) && (ivci.components.b != VK_COMPONENT_SWIZZLE_B)) || 883179fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis ((ivci.components.a != VK_COMPONENT_SWIZZLE_IDENTITY) && (ivci.components.a != VK_COMPONENT_SWIZZLE_A))) { 8832da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis skip_call |= log_msg( 88336fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 88349bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt VALIDATION_ERROR_00412, "DS", 8835da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis "vkCreateFramebuffer(): VkFramebufferCreateInfo attachment #%u has non-identy swizzle. All framebuffer " 8836da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis "attachments must have been created with the identity swizzle. Here are the actual swizzle values:\n" 8837da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis "r swizzle = %s\n" 8838da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis "g swizzle = %s\n" 8839da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis "b swizzle = %s\n" 88409bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "a swizzle = %s\n" 88419bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "%s", 884279fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis i, string_VkComponentSwizzle(ivci.components.r), string_VkComponentSwizzle(ivci.components.g), 88439bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt string_VkComponentSwizzle(ivci.components.b), string_VkComponentSwizzle(ivci.components.a), 88449bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt validation_error_map[VALIDATION_ERROR_00412]); 88455ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis } 88465ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis } 8847d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis } 88485ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis // Verify correct attachment usage flags 88496600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski for (uint32_t subpass = 0; subpass < rpci->subpassCount; subpass++) { 88506600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski // Verify input attachments: 88519bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt skip_call |= 88529bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt MatchUsage(dev_data, rpci->pSubpasses[subpass].inputAttachmentCount, rpci->pSubpasses[subpass].pInputAttachments, 88539bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt pCreateInfo, VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT, VALIDATION_ERROR_00407); 88546600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski // Verify color attachments: 88559bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt skip_call |= 88569bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt MatchUsage(dev_data, rpci->pSubpasses[subpass].colorAttachmentCount, rpci->pSubpasses[subpass].pColorAttachments, 88579bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt pCreateInfo, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VALIDATION_ERROR_00405); 88586600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski // Verify depth/stencil attachments: 88596600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski if (rpci->pSubpasses[subpass].pDepthStencilAttachment != nullptr) { 88606600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski skip_call |= MatchUsage(dev_data, 1, rpci->pSubpasses[subpass].pDepthStencilAttachment, pCreateInfo, 88619bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VALIDATION_ERROR_00406); 88626600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski } 88636600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski } 88646600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski } 88656fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis // Verify FB dimensions are within physical device limits 88669bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt if (pCreateInfo->width > dev_data->phys_dev_properties.properties.limits.maxFramebufferWidth) { 88676fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 88689bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt VALIDATION_ERROR_00413, "DS", 88699bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "vkCreateFramebuffer(): Requested VkFramebufferCreateInfo width exceeds physical device limits. " 88709bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "Requested width: %u, device max: %u\n" 88719bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "%s", 88726fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis pCreateInfo->width, dev_data->phys_dev_properties.properties.limits.maxFramebufferWidth, 88739bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt validation_error_map[VALIDATION_ERROR_00413]); 88749bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt } 88759bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt if (pCreateInfo->height > dev_data->phys_dev_properties.properties.limits.maxFramebufferHeight) { 88769bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 88779bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt VALIDATION_ERROR_00414, "DS", 88789bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "vkCreateFramebuffer(): Requested VkFramebufferCreateInfo height exceeds physical device limits. " 88799bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "Requested height: %u, device max: %u\n" 88809bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "%s", 88816fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis pCreateInfo->height, dev_data->phys_dev_properties.properties.limits.maxFramebufferHeight, 88829bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt validation_error_map[VALIDATION_ERROR_00414]); 88839bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt } 88849bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt if (pCreateInfo->layers > dev_data->phys_dev_properties.properties.limits.maxFramebufferLayers) { 88859bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 88869bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt VALIDATION_ERROR_00415, "DS", 88879bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "vkCreateFramebuffer(): Requested VkFramebufferCreateInfo layers exceeds physical device limits. " 88889bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "Requested layers: %u, device max: %u\n" 88899bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "%s", 88909bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt pCreateInfo->layers, dev_data->phys_dev_properties.properties.limits.maxFramebufferLayers, 88919bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt validation_error_map[VALIDATION_ERROR_00415]); 88926fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis } 88936600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski return skip_call; 88946600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski} 88956600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski 889664c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis// Validate VkFramebufferCreateInfo state prior to calling down chain to create Framebuffer object 889764c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis// Return true if an error is encountered and callback returns true to skip call down chain 889864c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis// false indicates that call down chain should proceed 889964c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlisstatic bool PreCallValidateCreateFramebuffer(layer_data *dev_data, const VkFramebufferCreateInfo *pCreateInfo) { 890064c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis // TODO : Verify that renderPass FB is created with is compatible with FB 890164c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis bool skip_call = false; 8902d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis skip_call |= ValidateFramebufferCreateInfo(dev_data, pCreateInfo); 890364c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis return skip_call; 890464c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis} 890564c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis 890654e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis// CreateFramebuffer state has been validated and call down chain completed so record new framebuffer object 890754e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlisstatic void PostCallRecordCreateFramebuffer(layer_data *dev_data, const VkFramebufferCreateInfo *pCreateInfo, VkFramebuffer fb) { 890854e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis // Shadow create info and store in map 8909c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis std::unique_ptr<FRAMEBUFFER_STATE> fb_state( 8910c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis new FRAMEBUFFER_STATE(fb, pCreateInfo, dev_data->renderPassMap[pCreateInfo->renderPass]->createInfo.ptr())); 891176f04ca0e692f9f15d5ef7e0c658c24d11f34ebcTobin Ehlis 891254e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) { 891354e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis VkImageView view = pCreateInfo->pAttachments[i]; 89149a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto view_state = GetImageViewState(dev_data, view); 891579fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis if (!view_state) { 891654e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis continue; 891754e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis } 891854e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis MT_FB_ATTACHMENT_INFO fb_info; 89199a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis fb_info.mem = GetImageState(dev_data, view_state->create_info.image)->binding.mem; 8920883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis fb_info.view_state = view_state; 892179fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis fb_info.image = view_state->create_info.image; 8922c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis fb_state->attachments.push_back(fb_info); 892354e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis } 8924c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis dev_data->frameBufferMap[fb] = std::move(fb_state); 892554e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis} 892654e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis 892789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateFramebuffer(VkDevice device, const VkFramebufferCreateInfo *pCreateInfo, 8928bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkFramebuffer *pFramebuffer) { 892956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 893064c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 893164c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis bool skip_call = PreCallValidateCreateFramebuffer(dev_data, pCreateInfo); 893264c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis lock.unlock(); 893364c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis 8934cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip_call) return VK_ERROR_VALIDATION_FAILED_EXT; 893564c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis 89364a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateFramebuffer(device, pCreateInfo, pAllocator, pFramebuffer); 89376600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski 89385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 893964c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis lock.lock(); 894054e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis PostCallRecordCreateFramebuffer(dev_data, pCreateInfo, *pFramebuffer); 894154e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis lock.unlock(); 89425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 89435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 89445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 89455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 89464e11bb1277f55311686a42000520791e1db1dd7bbungemanstatic bool FindDependency(const uint32_t index, const uint32_t dependent, const std::vector<DAGNode> &subpass_to_node, 8947e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves std::unordered_set<uint32_t> &processed_nodes) { 89485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // If we have already checked this node we have not found a dependency path so return false. 8949cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (processed_nodes.count(index)) return false; 89505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis processed_nodes.insert(index); 89515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const DAGNode &node = subpass_to_node[index]; 89525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Look for a dependency path. If one exists return true else recurse on the previous nodes. 89534e11bb1277f55311686a42000520791e1db1dd7bbungeman if (std::find(node.prev.begin(), node.prev.end(), dependent) == node.prev.end()) { 89545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto elem : node.prev) { 8955cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (FindDependency(elem, dependent, subpass_to_node, processed_nodes)) return true; 89565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 89575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 8958e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves return true; 89595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8960e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves return false; 89615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 89625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 89634e11bb1277f55311686a42000520791e1db1dd7bbungemanstatic bool CheckDependencyExists(const layer_data *dev_data, const uint32_t subpass, 89644e11bb1277f55311686a42000520791e1db1dd7bbungeman const std::vector<uint32_t> &dependent_subpasses, 8965e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves const std::vector<DAGNode> &subpass_to_node, bool &skip_call) { 8966e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool result = true; 89675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Loop through all subpasses that share the same attachment and make sure a dependency exists 89685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t k = 0; k < dependent_subpasses.size(); ++k) { 8969cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (static_cast<uint32_t>(subpass) == dependent_subpasses[k]) continue; 89705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const DAGNode &node = subpass_to_node[subpass]; 89715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Check for a specified dependency between the two nodes. If one exists we are done. 89725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto prev_elem = std::find(node.prev.begin(), node.prev.end(), dependent_subpasses[k]); 89735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto next_elem = std::find(node.next.begin(), node.next.end(), dependent_subpasses[k]); 89745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (prev_elem == node.prev.end() && next_elem == node.next.end()) { 89757655cb8b5eb52badee0b011729a05afa36316d69Jan-Harald Fredriksen // If no dependency exits an implicit dependency still might. If not, throw an error. 89765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_set<uint32_t> processed_nodes; 89777655cb8b5eb52badee0b011729a05afa36316d69Jan-Harald Fredriksen if (!(FindDependency(subpass, dependent_subpasses[k], subpass_to_node, processed_nodes) || 8978bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski FindDependency(dependent_subpasses[k], subpass, subpass_to_node, processed_nodes))) { 8979df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 8980df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski 0, __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS", 89815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis "A dependency between subpasses %d and %d must exist but one is not specified.", subpass, 89825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dependent_subpasses[k]); 8983e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves result = false; 89845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 89855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 89865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 89875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 89885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 89895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 89908860b85a52096f9f9b28616bc37feed505497a54Chris Forbesstatic bool CheckPreserved(const layer_data *dev_data, const VkRenderPassCreateInfo *pCreateInfo, const int index, 8991e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves const uint32_t attachment, const std::vector<DAGNode> &subpass_to_node, int depth, bool &skip_call) { 89925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const DAGNode &node = subpass_to_node[index]; 89935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // If this node writes to the attachment return true as next nodes need to preserve the attachment. 89945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[index]; 89955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) { 8996cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (attachment == subpass.pColorAttachments[j].attachment) return true; 89975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8998a4ea781e8fff70c9db0bedad7fcb6bba08e35da7Tony Barbour for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) { 8999a4ea781e8fff70c9db0bedad7fcb6bba08e35da7Tony Barbour if (attachment == subpass.pInputAttachments[j].attachment) return true; 9000a4ea781e8fff70c9db0bedad7fcb6bba08e35da7Tony Barbour } 90015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) { 9002cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (attachment == subpass.pDepthStencilAttachment->attachment) return true; 90035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9004e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool result = false; 90055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Loop through previous nodes and see if any of them write to the attachment. 90065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto elem : node.prev) { 90078860b85a52096f9f9b28616bc37feed505497a54Chris Forbes result |= CheckPreserved(dev_data, pCreateInfo, elem, attachment, subpass_to_node, depth + 1, skip_call); 90085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 90095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // If the attachment was written to by a previous node than this node needs to preserve it. 90105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (result && depth > 0) { 9011e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool has_preserved = false; 90125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t j = 0; j < subpass.preserveAttachmentCount; ++j) { 90135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (subpass.pPreserveAttachments[j] == attachment) { 9014e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves has_preserved = true; 90155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis break; 90165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 90175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9018e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves if (!has_preserved) { 90195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis skip_call |= 9020df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 90215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis DRAWSTATE_INVALID_RENDERPASS, "DS", 90225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis "Attachment %d is used by a later subpass and must be preserved in subpass %d.", attachment, index); 90235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 90245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 90255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 90265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 90275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9028cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskitemplate <class T> 9029cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskibool isRangeOverlapping(T offset1, T size1, T offset2, T size2) { 90305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return (((offset1 + size1) > offset2) && ((offset1 + size1) < (offset2 + size2))) || 90315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis ((offset1 > offset2) && (offset1 < (offset2 + size2))); 90325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 90335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 90345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisbool isRegionOverlapping(VkImageSubresourceRange range1, VkImageSubresourceRange range2) { 90355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return (isRangeOverlapping(range1.baseMipLevel, range1.levelCount, range2.baseMipLevel, range2.levelCount) && 90365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis isRangeOverlapping(range1.baseArrayLayer, range1.layerCount, range2.baseArrayLayer, range2.layerCount)); 90375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 90385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9039c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlisstatic bool ValidateDependencies(const layer_data *dev_data, FRAMEBUFFER_STATE const *framebuffer, 9040127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis RENDER_PASS_STATE const *renderPass) { 9041e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool skip_call = false; 9042fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes auto const pFramebufferInfo = framebuffer->createInfo.ptr(); 9043fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes auto const pCreateInfo = renderPass->createInfo.ptr(); 9044bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto const &subpass_to_node = renderPass->subpassToNode; 90455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::vector<std::vector<uint32_t>> output_attachment_to_subpass(pCreateInfo->attachmentCount); 90465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::vector<std::vector<uint32_t>> input_attachment_to_subpass(pCreateInfo->attachmentCount); 90475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::vector<std::vector<uint32_t>> overlapping_attachments(pCreateInfo->attachmentCount); 90485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Find overlapping attachments 90495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) { 90505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t j = i + 1; j < pCreateInfo->attachmentCount; ++j) { 90515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkImageView viewi = pFramebufferInfo->pAttachments[i]; 90525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkImageView viewj = pFramebufferInfo->pAttachments[j]; 90535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (viewi == viewj) { 90545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis overlapping_attachments[i].push_back(j); 90555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis overlapping_attachments[j].push_back(i); 90565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis continue; 90575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 90589a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto view_state_i = GetImageViewState(dev_data, viewi); 90599a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto view_state_j = GetImageViewState(dev_data, viewj); 906079fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis if (!view_state_i || !view_state_j) { 90615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis continue; 90625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 906379fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis auto view_ci_i = view_state_i->create_info; 906479fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis auto view_ci_j = view_state_j->create_info; 906579fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis if (view_ci_i.image == view_ci_j.image && isRegionOverlapping(view_ci_i.subresourceRange, view_ci_j.subresourceRange)) { 90665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis overlapping_attachments[i].push_back(j); 90675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis overlapping_attachments[j].push_back(i); 90685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis continue; 90695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 90709a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_data_i = GetImageState(dev_data, view_ci_i.image); 90719a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_data_j = GetImageState(dev_data, view_ci_j.image); 90726d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis if (!image_data_i || !image_data_j) { 90735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis continue; 90745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9075e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis if (image_data_i->binding.mem == image_data_j->binding.mem && 9076e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis isRangeOverlapping(image_data_i->binding.offset, image_data_i->binding.size, image_data_j->binding.offset, 9077e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis image_data_j->binding.size)) { 90785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis overlapping_attachments[i].push_back(j); 90795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis overlapping_attachments[j].push_back(i); 90805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 90815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 90825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 90835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < overlapping_attachments.size(); ++i) { 90845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t attachment = i; 90855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto other_attachment : overlapping_attachments[i]) { 90865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!(pCreateInfo->pAttachments[attachment].flags & VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT)) { 9087df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= 9088df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT, 9089df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<const uint64_t &>(framebuffer->framebuffer), __LINE__, VALIDATION_ERROR_00324, "DS", 9090df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "Attachment %d aliases attachment %d but doesn't " 9091df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "set VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT. %s", 9092df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski attachment, other_attachment, validation_error_map[VALIDATION_ERROR_00324]); 90935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 90945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!(pCreateInfo->pAttachments[other_attachment].flags & VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT)) { 9095df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= 9096df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT, 9097df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<const uint64_t &>(framebuffer->framebuffer), __LINE__, VALIDATION_ERROR_00324, "DS", 9098df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "Attachment %d aliases attachment %d but doesn't " 9099df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "set VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT. %s", 9100df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski other_attachment, attachment, validation_error_map[VALIDATION_ERROR_00324]); 91015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 91025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 91035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 91045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Find for each attachment the subpasses that use them. 91051c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young unordered_set<uint32_t> attachmentIndices; 91065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) { 91075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i]; 91081c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young attachmentIndices.clear(); 91095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) { 91105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t attachment = subpass.pInputAttachments[j].attachment; 9111cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (attachment == VK_ATTACHMENT_UNUSED) continue; 91125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis input_attachment_to_subpass[attachment].push_back(i); 91135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto overlapping_attachment : overlapping_attachments[attachment]) { 91145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis input_attachment_to_subpass[overlapping_attachment].push_back(i); 91155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 91165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 91175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) { 91185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t attachment = subpass.pColorAttachments[j].attachment; 9119cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (attachment == VK_ATTACHMENT_UNUSED) continue; 91205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis output_attachment_to_subpass[attachment].push_back(i); 91215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto overlapping_attachment : overlapping_attachments[attachment]) { 91225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis output_attachment_to_subpass[overlapping_attachment].push_back(i); 91235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 91241c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young attachmentIndices.insert(attachment); 91255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 91265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) { 91275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t attachment = subpass.pDepthStencilAttachment->attachment; 91285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis output_attachment_to_subpass[attachment].push_back(i); 91295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto overlapping_attachment : overlapping_attachments[attachment]) { 91305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis output_attachment_to_subpass[overlapping_attachment].push_back(i); 91315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 91321c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young 91331c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young if (attachmentIndices.count(attachment)) { 91341c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young skip_call |= 9135df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 9136df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS", 91378860b85a52096f9f9b28616bc37feed505497a54Chris Forbes "Cannot use same attachment (%u) as both color and depth output in same subpass (%u).", attachment, i); 91381c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young } 91395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 91405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 91415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // If there is a dependency needed make sure one exists 91425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) { 91435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i]; 91445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // If the attachment is an input then all subpasses that output must have a dependency relationship 91455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) { 914693fe72ec8460857bdb3c101095e6eb96d6171341Chris Forbes uint32_t attachment = subpass.pInputAttachments[j].attachment; 9147cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (attachment == VK_ATTACHMENT_UNUSED) continue; 91488860b85a52096f9f9b28616bc37feed505497a54Chris Forbes CheckDependencyExists(dev_data, i, output_attachment_to_subpass[attachment], subpass_to_node, skip_call); 91495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 91505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // If the attachment is an output then all subpasses that use the attachment must have a dependency relationship 91515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) { 915293fe72ec8460857bdb3c101095e6eb96d6171341Chris Forbes uint32_t attachment = subpass.pColorAttachments[j].attachment; 9153cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (attachment == VK_ATTACHMENT_UNUSED) continue; 91548860b85a52096f9f9b28616bc37feed505497a54Chris Forbes CheckDependencyExists(dev_data, i, output_attachment_to_subpass[attachment], subpass_to_node, skip_call); 91558860b85a52096f9f9b28616bc37feed505497a54Chris Forbes CheckDependencyExists(dev_data, i, input_attachment_to_subpass[attachment], subpass_to_node, skip_call); 91565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 91575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) { 91585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const uint32_t &attachment = subpass.pDepthStencilAttachment->attachment; 91598860b85a52096f9f9b28616bc37feed505497a54Chris Forbes CheckDependencyExists(dev_data, i, output_attachment_to_subpass[attachment], subpass_to_node, skip_call); 91608860b85a52096f9f9b28616bc37feed505497a54Chris Forbes CheckDependencyExists(dev_data, i, input_attachment_to_subpass[attachment], subpass_to_node, skip_call); 91615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 91625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 91635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Loop through implicit dependencies, if this pass reads make sure the attachment is preserved for all passes after it was 91645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // written. 91655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) { 91665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i]; 91675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) { 91688860b85a52096f9f9b28616bc37feed505497a54Chris Forbes CheckPreserved(dev_data, pCreateInfo, i, subpass.pInputAttachments[j].attachment, subpass_to_node, 0, skip_call); 91695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 91705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 91715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return skip_call; 91725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 91735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 91748860b85a52096f9f9b28616bc37feed505497a54Chris Forbesstatic bool CreatePassDAG(const layer_data *dev_data, VkDevice device, const VkRenderPassCreateInfo *pCreateInfo, 9175e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves std::vector<DAGNode> &subpass_to_node, std::vector<bool> &has_self_dependency) { 9176e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool skip_call = false; 91775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) { 91785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis DAGNode &subpass_node = subpass_to_node[i]; 91795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis subpass_node.pass = i; 91805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 91815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->dependencyCount; ++i) { 91825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkSubpassDependency &dependency = pCreateInfo->pDependencies[i]; 918366a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes if (dependency.srcSubpass == VK_SUBPASS_EXTERNAL || dependency.dstSubpass == VK_SUBPASS_EXTERNAL) { 918466a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes if (dependency.srcSubpass == dependency.dstSubpass) { 918566a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes skip_call |= 9186df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 9187df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS", "The src and dest subpasses cannot both be external."); 918866a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes } 918966a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes } else if (dependency.srcSubpass > dependency.dstSubpass) { 9190df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 9191df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS", 91925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis "Depedency graph must be specified such that an earlier pass cannot depend on a later pass."); 91935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (dependency.srcSubpass == dependency.dstSubpass) { 91945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis has_self_dependency[dependency.srcSubpass] = true; 91955c6aacf95832467d52b2fde1130b04bef559573aChris Forbes } else { 91965c6aacf95832467d52b2fde1130b04bef559573aChris Forbes subpass_to_node[dependency.dstSubpass].prev.push_back(dependency.srcSubpass); 91975c6aacf95832467d52b2fde1130b04bef559573aChris Forbes subpass_to_node[dependency.srcSubpass].next.push_back(dependency.dstSubpass); 91985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 91995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 92005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return skip_call; 92015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 9202918c283ac4f8c604b79abd0c8b5706d2a7352a34Chris Forbes 920389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo *pCreateInfo, 9204bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkShaderModule *pShaderModule) { 920556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 9206e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool skip_call = false; 9207c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski spv_result_t spv_valid = SPV_SUCCESS; 9208b1f65702539fd041337fccd493dc6d38dd2a603eChris Forbes 9209e3443707b0f51ba7c6c458c5039dd3004c38b73eMark Lobodzinski if (!GetDisables(dev_data)->shader_validation) { 9210e3443707b0f51ba7c6c458c5039dd3004c38b73eMark Lobodzinski // Use SPIRV-Tools validator to try and catch any issues with the module itself 9211e3443707b0f51ba7c6c458c5039dd3004c38b73eMark Lobodzinski spv_context ctx = spvContextCreate(SPV_ENV_VULKAN_1_0); 9212e3443707b0f51ba7c6c458c5039dd3004c38b73eMark Lobodzinski spv_const_binary_t binary{pCreateInfo->pCode, pCreateInfo->codeSize / sizeof(uint32_t)}; 9213e3443707b0f51ba7c6c458c5039dd3004c38b73eMark Lobodzinski spv_diagnostic diag = nullptr; 9214b1f65702539fd041337fccd493dc6d38dd2a603eChris Forbes 9215c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski spv_valid = spvValidate(ctx, &binary, &diag); 9216c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski if (spv_valid != SPV_SUCCESS) { 92175581a92674a04d2ef49fde417e657f64e3aeed69Mark Lobodzinski if (!dev_data->device_extensions.nv_glsl_shader_enabled || (pCreateInfo->pCode[0] == spv::MagicNumber)) { 9218c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski skip_call |= log_msg(dev_data->report_data, 9219c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski spv_valid == SPV_WARNING ? VK_DEBUG_REPORT_WARNING_BIT_EXT : VK_DEBUG_REPORT_ERROR_BIT_EXT, 9220c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski VkDebugReportObjectTypeEXT(0), 0, __LINE__, SHADER_CHECKER_INCONSISTENT_SPIRV, "SC", 9221c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski "SPIR-V module not valid: %s", diag && diag->error ? diag->error : "(no error text)"); 9222c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski } 9223e3443707b0f51ba7c6c458c5039dd3004c38b73eMark Lobodzinski } 92245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9225e3443707b0f51ba7c6c458c5039dd3004c38b73eMark Lobodzinski spvDiagnosticDestroy(diag); 9226e3443707b0f51ba7c6c458c5039dd3004c38b73eMark Lobodzinski spvContextDestroy(ctx); 9227b1f65702539fd041337fccd493dc6d38dd2a603eChris Forbes 9228e3443707b0f51ba7c6c458c5039dd3004c38b73eMark Lobodzinski if (skip_call) return VK_ERROR_VALIDATION_FAILED_EXT; 9229e3443707b0f51ba7c6c458c5039dd3004c38b73eMark Lobodzinski } 92305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 92314a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult res = dev_data->dispatch_table.CreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule); 92325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9233e3443707b0f51ba7c6c458c5039dd3004c38b73eMark Lobodzinski if (res == VK_SUCCESS && !GetDisables(dev_data)->shader_validation) { 9234b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 9235c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski const auto new_shader_module = (SPV_SUCCESS == spv_valid ? new shader_module(pCreateInfo) : new shader_module()); 9236c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski dev_data->shaderModuleMap[*pShaderModule] = unique_ptr<shader_module>(new_shader_module); 92375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 92385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return res; 92395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 92405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 92414f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinskistatic bool ValidateAttachmentIndex(layer_data *dev_data, uint32_t attachment, uint32_t attachment_count, const char *type) { 92424f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski bool skip_call = false; 92434f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski if (attachment >= attachment_count && attachment != VK_ATTACHMENT_UNUSED) { 9244df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 9245df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski __LINE__, VALIDATION_ERROR_00325, "DS", 9246bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "CreateRenderPass: %s attachment %d must be less than the total number of attachments %d. %s", type, 9247bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski attachment, attachment_count, validation_error_map[VALIDATION_ERROR_00325]); 92484f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 92494f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski return skip_call; 92504f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski} 92514f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski 9252bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic bool IsPowerOfTwo(unsigned x) { return x && !(x & (x - 1)); } 9253805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes 92544f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinskistatic bool ValidateRenderpassAttachmentUsage(layer_data *dev_data, const VkRenderPassCreateInfo *pCreateInfo) { 92554f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski bool skip_call = false; 92564f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) { 92574f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i]; 92584f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski if (subpass.pipelineBindPoint != VK_PIPELINE_BIND_POINT_GRAPHICS) { 9259df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 9260df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski __LINE__, VALIDATION_ERROR_00347, "DS", 92619bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "CreateRenderPass: Pipeline bind point for subpass %d must be VK_PIPELINE_BIND_POINT_GRAPHICS. %s", 92629bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt i, validation_error_map[VALIDATION_ERROR_00347]); 92634f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 92644f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski for (uint32_t j = 0; j < subpass.preserveAttachmentCount; ++j) { 92654f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski uint32_t attachment = subpass.pPreserveAttachments[j]; 92664f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski if (attachment == VK_ATTACHMENT_UNUSED) { 9267df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 9268df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski 0, __LINE__, VALIDATION_ERROR_00356, "DS", 92699bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "CreateRenderPass: Preserve attachment (%d) must not be VK_ATTACHMENT_UNUSED. %s", j, 92709bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt validation_error_map[VALIDATION_ERROR_00356]); 92714f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } else { 92724f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski skip_call |= ValidateAttachmentIndex(dev_data, attachment, pCreateInfo->attachmentCount, "Preserve"); 92734f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 92744f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 92756a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes 9276bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto subpass_performs_resolve = 9277bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski subpass.pResolveAttachments && 9278bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski std::any_of(subpass.pResolveAttachments, subpass.pResolveAttachments + subpass.colorAttachmentCount, 9279bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski [](VkAttachmentReference ref) { return ref.attachment != VK_ATTACHMENT_UNUSED; }); 92806a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes 9281805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes unsigned sample_count = 0; 9282805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes 92834f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) { 92844f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski uint32_t attachment; 92854f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski if (subpass.pResolveAttachments) { 92864f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski attachment = subpass.pResolveAttachments[j].attachment; 92874f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski skip_call |= ValidateAttachmentIndex(dev_data, attachment, pCreateInfo->attachmentCount, "Resolve"); 92886a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes 92896a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes if (!skip_call && attachment != VK_ATTACHMENT_UNUSED && 92906a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes pCreateInfo->pAttachments[attachment].samples != VK_SAMPLE_COUNT_1_BIT) { 92916a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, 92929bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt __LINE__, VALIDATION_ERROR_00352, "DS", 92936a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes "CreateRenderPass: Subpass %u requests multisample resolve into attachment %u, " 92949bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "which must have VK_SAMPLE_COUNT_1_BIT but has %s. %s", 92959bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt i, attachment, string_VkSampleCountFlagBits(pCreateInfo->pAttachments[attachment].samples), 92969bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt validation_error_map[VALIDATION_ERROR_00352]); 92976a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes } 92984f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 92994f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski attachment = subpass.pColorAttachments[j].attachment; 93004f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski skip_call |= ValidateAttachmentIndex(dev_data, attachment, pCreateInfo->attachmentCount, "Color"); 93016a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes 9302805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes if (!skip_call && attachment != VK_ATTACHMENT_UNUSED) { 9303805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes sample_count |= (unsigned)pCreateInfo->pAttachments[attachment].samples; 9304805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes 9305bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (subpass_performs_resolve && pCreateInfo->pAttachments[attachment].samples == VK_SAMPLE_COUNT_1_BIT) { 9306dc7c45f01ae5690f7c969b4760463c1a6bac52d5Chris Forbes skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, 93079bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt __LINE__, VALIDATION_ERROR_00351, "DS", 9308dc7c45f01ae5690f7c969b4760463c1a6bac52d5Chris Forbes "CreateRenderPass: Subpass %u requests multisample resolve from attachment %u " 93099bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "which has VK_SAMPLE_COUNT_1_BIT. %s", 93109bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt i, attachment, validation_error_map[VALIDATION_ERROR_00351]); 9311dc7c45f01ae5690f7c969b4760463c1a6bac52d5Chris Forbes } 93126a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes } 93134f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 9314dc7c45f01ae5690f7c969b4760463c1a6bac52d5Chris Forbes 93154f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) { 93164f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski uint32_t attachment = subpass.pDepthStencilAttachment->attachment; 93174f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski skip_call |= ValidateAttachmentIndex(dev_data, attachment, pCreateInfo->attachmentCount, "Depth stencil"); 9318805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes 9319805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes if (!skip_call && attachment != VK_ATTACHMENT_UNUSED) { 9320805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes sample_count |= (unsigned)pCreateInfo->pAttachments[attachment].samples; 9321805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes } 93224f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 9323dc7c45f01ae5690f7c969b4760463c1a6bac52d5Chris Forbes 93244f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) { 93254f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski uint32_t attachment = subpass.pInputAttachments[j].attachment; 93264f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski skip_call |= ValidateAttachmentIndex(dev_data, attachment, pCreateInfo->attachmentCount, "Input"); 93274f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 9328805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes 9329805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes if (sample_count && !IsPowerOfTwo(sample_count)) { 93309bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, 9331cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VALIDATION_ERROR_00337, "DS", 9332cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "CreateRenderPass: Subpass %u attempts to render to " 9333cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "attachments with inconsistent sample counts. %s", 93349bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt i, validation_error_map[VALIDATION_ERROR_00337]); 9335805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes } 93364f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 93374f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski return skip_call; 93384f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski} 93394f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski 93405245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbesstatic void MarkAttachmentFirstUse(RENDER_PASS_STATE *render_pass, 93415245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes uint32_t index, 93425245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes bool is_read) { 93435245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes if (index == VK_ATTACHMENT_UNUSED) 93445245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes return; 93455245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes 93465245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes if (!render_pass->attachment_first_read.count(index)) 93475245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes render_pass->attachment_first_read[index] = is_read; 93485245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes} 93495245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes 935089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateRenderPass(VkDevice device, const VkRenderPassCreateInfo *pCreateInfo, 93514f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass) { 9352e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool skip_call = false; 935356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 93544f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski 93554f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski std::unique_lock<std::mutex> lock(global_lock); 93564f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski // TODO: As part of wrapping up the mem_tracker/core_validation merge the following routine should be consolidated with 93574f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski // ValidateLayouts. 93584f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski skip_call |= ValidateRenderpassAttachmentUsage(dev_data, pCreateInfo); 9359208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->dependencyCount; ++i) { 9360208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis skip_call |= ValidateStageMaskGsTsEnables(dev_data, pCreateInfo->pDependencies[i].srcStageMask, "vkCreateRenderPass()", 9361208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis VALIDATION_ERROR_00368, VALIDATION_ERROR_00370); 9362208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis skip_call |= ValidateStageMaskGsTsEnables(dev_data, pCreateInfo->pDependencies[i].dstStageMask, "vkCreateRenderPass()", 9363208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis VALIDATION_ERROR_00369, VALIDATION_ERROR_00371); 9364208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis } 9365ab38df28c5ae1816c5fa33c0c7840c6950e83f0dChris Forbes if (!skip_call) { 9366ab38df28c5ae1816c5fa33c0c7840c6950e83f0dChris Forbes skip_call |= ValidateLayouts(dev_data, device, pCreateInfo); 9367ab38df28c5ae1816c5fa33c0c7840c6950e83f0dChris Forbes } 9368ff6101de02d1677fb54962e2ff57875e76898e26Chris Forbes lock.unlock(); 93694f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski 93704f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski if (skip_call) { 93714f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski return VK_ERROR_VALIDATION_FAILED_EXT; 93724f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 93734f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski 93744a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateRenderPass(device, pCreateInfo, pAllocator, pRenderPass); 9375ff6101de02d1677fb54962e2ff57875e76898e26Chris Forbes 93765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 93774f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski lock.lock(); 93784f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski 93794f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski std::vector<bool> has_self_dependency(pCreateInfo->subpassCount); 93804f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski std::vector<DAGNode> subpass_to_node(pCreateInfo->subpassCount); 93814f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski skip_call |= CreatePassDAG(dev_data, device, pCreateInfo, subpass_to_node, has_self_dependency); 93824f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski 9383127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis auto render_pass = unique_ptr<RENDER_PASS_STATE>(new RENDER_PASS_STATE(pCreateInfo)); 938498cddf7090b5d5dcc382045867753ef703d1c3d3Chris Forbes render_pass->renderPass = *pRenderPass; 9385cf2686cdbb12af8a29ca598c126b5e37215f0ef7Chris Forbes render_pass->hasSelfDependency = has_self_dependency; 9386cf2686cdbb12af8a29ca598c126b5e37215f0ef7Chris Forbes render_pass->subpassToNode = subpass_to_node; 9387db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes 938887e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) { 938987e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i]; 939087e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) { 93915245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes MarkAttachmentFirstUse(render_pass.get(), subpass.pColorAttachments[j].attachment, false); 93929cde292b1c19c643b7c13018d9834cccfe6ef7eaChris Forbes 93935245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes // resolve attachments are considered to be written 93945245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes if (subpass.pResolveAttachments) { 93955245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes MarkAttachmentFirstUse(render_pass.get(), subpass.pResolveAttachments[j].attachment, false); 93969cde292b1c19c643b7c13018d9834cccfe6ef7eaChris Forbes } 939787e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis } 93985245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes if (subpass.pDepthStencilAttachment) { 93995245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes MarkAttachmentFirstUse(render_pass.get(), subpass.pDepthStencilAttachment->attachment, false); 940087e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis } 9401a5ce96d7c88653668a2b33a6b72bd3cb16d73f48Michael Lentine for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) { 94025245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes MarkAttachmentFirstUse(render_pass.get(), subpass.pInputAttachments[j].attachment, true); 9403a5ce96d7c88653668a2b33a6b72bd3cb16d73f48Michael Lentine } 940487e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis } 9405db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes 9406fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes dev_data->renderPassMap[*pRenderPass] = std::move(render_pass); 94075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 94085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 94095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 94104f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski 94119bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardtstatic bool validatePrimaryCommandBuffer(const layer_data *dev_data, const GLOBAL_CB_NODE *pCB, const std::string &cmd_name, 94129bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt UNIQUE_VALIDATION_ERROR_CODE error_code) { 9413e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool skip_call = false; 94145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB->createInfo.level != VK_COMMAND_BUFFER_LEVEL_PRIMARY) { 9415df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 9416df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(pCB->commandBuffer), __LINE__, error_code, "DS", 9417df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "Cannot execute command %s on a secondary command buffer. %s", cmd_name.c_str(), 94189bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt validation_error_map[error_code]); 94195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 94205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return skip_call; 94215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 94225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 94238860b85a52096f9f9b28616bc37feed505497a54Chris Forbesstatic bool VerifyRenderAreaBounds(const layer_data *dev_data, const VkRenderPassBeginInfo *pRenderPassBegin) { 9424885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine bool skip_call = false; 9425c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis const safe_VkFramebufferCreateInfo *pFramebufferInfo = 94269a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis &GetFramebufferState(dev_data, pRenderPassBegin->framebuffer)->createInfo; 9427885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine if (pRenderPassBegin->renderArea.offset.x < 0 || 9428885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine (pRenderPassBegin->renderArea.offset.x + pRenderPassBegin->renderArea.extent.width) > pFramebufferInfo->width || 9429885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine pRenderPassBegin->renderArea.offset.y < 0 || 9430885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine (pRenderPassBegin->renderArea.offset.y + pRenderPassBegin->renderArea.extent.height) > pFramebufferInfo->height) { 9431885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine skip_call |= static_cast<bool>(log_msg( 9432df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 9433885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine DRAWSTATE_INVALID_RENDER_AREA, "CORE", 9434885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine "Cannot execute a render pass with renderArea not within the bound of the " 9435885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine "framebuffer. RenderArea: x %d, y %d, width %d, height %d. Framebuffer: width %d, " 9436885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine "height %d.", 9437885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine pRenderPassBegin->renderArea.offset.x, pRenderPassBegin->renderArea.offset.y, pRenderPassBegin->renderArea.extent.width, 9438885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine pRenderPassBegin->renderArea.extent.height, pFramebufferInfo->width, pFramebufferInfo->height)); 9439885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine } 9440885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine return skip_call; 9441885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine} 9442885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine 94431a65650f856376768d7b03ea2d080aaff87cacfdMark 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 94441a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski// [load|store]Op flag must be checked 94451a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski// TODO: The memory valid flag in DEVICE_MEM_INFO should probably be split to track the validity of stencil memory separately. 9446cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskitemplate <typename T> 9447cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskistatic bool FormatSpecificLoadAndStoreOpSettings(VkFormat format, T color_depth_op, T stencil_op, T op) { 9448a49b8a211ce07e7fa2225d23f8cb11f1055b418aMark Lobodzinski if (color_depth_op != op && stencil_op != op) { 9449a49b8a211ce07e7fa2225d23f8cb11f1055b418aMark Lobodzinski return false; 9450a49b8a211ce07e7fa2225d23f8cb11f1055b418aMark Lobodzinski } 94511a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski bool check_color_depth_load_op = !vk_format_is_stencil_only(format); 94521a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski bool check_stencil_load_op = vk_format_is_depth_and_stencil(format) || !check_color_depth_load_op; 9453a49b8a211ce07e7fa2225d23f8cb11f1055b418aMark Lobodzinski 9454a49b8a211ce07e7fa2225d23f8cb11f1055b418aMark Lobodzinski return (((check_color_depth_load_op == true) && (color_depth_op == op)) || 9455a49b8a211ce07e7fa2225d23f8cb11f1055b418aMark Lobodzinski ((check_stencil_load_op == true) && (stencil_op == op))); 94561a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski} 94571a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski 9458bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBeginRenderPass(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *pRenderPassBegin, 9459bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkSubpassContents contents) { 946083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 946156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 9462b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 94639a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *cb_node = GetCBNode(dev_data, commandBuffer); 94649a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto render_pass_state = pRenderPassBegin ? GetRenderPassState(dev_data, pRenderPassBegin->renderPass) : nullptr; 94659a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto framebuffer = pRenderPassBegin ? GetFramebufferState(dev_data, pRenderPassBegin->framebuffer) : nullptr; 9466f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis if (cb_node) { 9467308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski if (render_pass_state) { 9468cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski uint32_t clear_op_size = 0; // Make sure pClearValues is at least as large as last LOAD_OP_CLEAR 9469f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->activeFramebuffer = pRenderPassBegin->framebuffer; 9470308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski for (uint32_t i = 0; i < render_pass_state->createInfo.attachmentCount; ++i) { 9471f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes MT_FB_ATTACHMENT_INFO &fb_info = framebuffer->attachments[i]; 9472308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski auto pAttachment = &render_pass_state->createInfo.pAttachments[i]; 9473bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (FormatSpecificLoadAndStoreOpSettings(pAttachment->format, pAttachment->loadOp, pAttachment->stencilLoadOp, 94741a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski VK_ATTACHMENT_LOAD_OP_CLEAR)) { 947592bc0680357019834b7529148ab6d73353ce02c7Mark Lobodzinski clear_op_size = static_cast<uint32_t>(i) + 1; 947616387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes std::function<bool()> function = [=]() { 94779a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis SetImageMemoryValid(dev_data, GetImageState(dev_data, fb_info.image), true); 947816387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes return false; 947916387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes }; 9480f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->validate_functions.push_back(function); 9481db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes } else if (FormatSpecificLoadAndStoreOpSettings(pAttachment->format, pAttachment->loadOp, 9482bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pAttachment->stencilLoadOp, VK_ATTACHMENT_LOAD_OP_DONT_CARE)) { 948316387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes std::function<bool()> function = [=]() { 94849a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis SetImageMemoryValid(dev_data, GetImageState(dev_data, fb_info.image), false); 948516387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes return false; 948616387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes }; 9487f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->validate_functions.push_back(function); 9488db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes } else if (FormatSpecificLoadAndStoreOpSettings(pAttachment->format, pAttachment->loadOp, 9489bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pAttachment->stencilLoadOp, VK_ATTACHMENT_LOAD_OP_LOAD)) { 949016387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes std::function<bool()> function = [=]() { 94919a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis return ValidateImageMemoryIsValid(dev_data, GetImageState(dev_data, fb_info.image), 9492f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis "vkCmdBeginRenderPass()"); 949316387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes }; 9494f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->validate_functions.push_back(function); 949516387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes } 9496308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski if (render_pass_state->attachment_first_read[i]) { 949716387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes std::function<bool()> function = [=]() { 94989a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis return ValidateImageMemoryIsValid(dev_data, GetImageState(dev_data, fb_info.image), 9499f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis "vkCmdBeginRenderPass()"); 950016387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes }; 9501f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->validate_functions.push_back(function); 95025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 95035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 95046de3c6ffa0819ee37cd5cecee918b062145e2ff1Tobin Ehlis if (clear_op_size > pRenderPassBegin->clearValueCount) { 9505369cf6deef1fca74f9eb1f8ef6e96deba715b133Slawomir Cygan skip_call |= log_msg( 9506369cf6deef1fca74f9eb1f8ef6e96deba715b133Slawomir Cygan dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT, 9507308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski reinterpret_cast<uint64_t &>(render_pass_state->renderPass), __LINE__, VALIDATION_ERROR_00442, "DS", 9508bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "In vkCmdBeginRenderPass() the VkRenderPassBeginInfo struct has a clearValueCount of %u but there must " 9509bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "be at least %u entries in pClearValues array to account for the highest index attachment in renderPass " 9510cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "0x%" PRIx64 9511cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " that uses VK_ATTACHMENT_LOAD_OP_CLEAR is %u. Note that the pClearValues array " 9512bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "is indexed by attachment number so even if some pClearValues entries between 0 and %u correspond to " 9513bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "attachments that aren't cleared they will be ignored. %s", 9514308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski pRenderPassBegin->clearValueCount, clear_op_size, reinterpret_cast<uint64_t &>(render_pass_state->renderPass), 95155504d0369cbc97ad7c221eddbad439bfb83e3fb6Mark Lobodzinski clear_op_size, clear_op_size - 1, validation_error_map[VALIDATION_ERROR_00442]); 9516369cf6deef1fca74f9eb1f8ef6e96deba715b133Slawomir Cygan } 9517369cf6deef1fca74f9eb1f8ef6e96deba715b133Slawomir Cygan if (clear_op_size < pRenderPassBegin->clearValueCount) { 9518369cf6deef1fca74f9eb1f8ef6e96deba715b133Slawomir Cygan skip_call |= log_msg( 9519369cf6deef1fca74f9eb1f8ef6e96deba715b133Slawomir Cygan dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT, 9520308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski reinterpret_cast<uint64_t &>(render_pass_state->renderPass), __LINE__, 9521308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski DRAWSTATE_RENDERPASS_TOO_MANY_CLEAR_VALUES, "DS", 9522369cf6deef1fca74f9eb1f8ef6e96deba715b133Slawomir Cygan "In vkCmdBeginRenderPass() the VkRenderPassBeginInfo struct has a clearValueCount of %u but only first %u " 95237bab3d8f0599701f6e26a2d76314588486ae99c9Mark Lobodzinski "entries in pClearValues array are used. The highest index of any attachment in renderPass 0x%" PRIx64 9524369cf6deef1fca74f9eb1f8ef6e96deba715b133Slawomir Cygan " that uses VK_ATTACHMENT_LOAD_OP_CLEAR is %u - other pClearValues are ignored.", 9525308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski pRenderPassBegin->clearValueCount, clear_op_size, reinterpret_cast<uint64_t &>(render_pass_state->renderPass), 95267bab3d8f0599701f6e26a2d76314588486ae99c9Mark Lobodzinski clear_op_size - 1); 95273d71bca42a843966040d6ada9c029e0ec9f35ca6Tobin Ehlis } 952883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= VerifyRenderAreaBounds(dev_data, pRenderPassBegin); 952955867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski skip_call |= VerifyFramebufferAndRenderPassLayouts(dev_data, cb_node, pRenderPassBegin, 95309a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GetFramebufferState(dev_data, pRenderPassBegin->framebuffer)); 9531ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen skip_call |= insideRenderPass(dev_data, cb_node, "vkCmdBeginRenderPass()", VALIDATION_ERROR_00440); 9532308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski skip_call |= ValidateDependencies(dev_data, framebuffer, render_pass_state); 95339bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt skip_call |= validatePrimaryCommandBuffer(dev_data, cb_node, "vkCmdBeginRenderPass", VALIDATION_ERROR_00441); 9534baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip_call |= 9535baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt ValidateCmdQueueFlags(dev_data, cb_node, "vkCmdBeginRenderPass()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_00439); 953629f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, cb_node, CMD_BEGINRENDERPASS, "vkCmdBeginRenderPass()"); 95371ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(cb_node, CMD_BEGINRENDERPASS); 9538308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski cb_node->activeRenderPass = render_pass_state; 95395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // This is a shallow copy as that is all that is needed for now 9540f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->activeRenderPassBeginInfo = *pRenderPassBegin; 9541f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->activeSubpass = 0; 9542f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->activeSubpassContents = contents; 9543f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->framebuffers.insert(pRenderPassBegin->framebuffer); 9544883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis // Connect this framebuffer and its children to this cmdBuffer 9545883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis AddFramebufferBinding(dev_data, cb_node, framebuffer); 9546ea0f86230ff5c52f805ac831a1ed5a92bd123368Chris Forbes // transition attachments to the correct layouts for the first subpass 954755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski TransitionSubpassLayouts(dev_data, cb_node, &cb_node->activeRenderPassBeginInfo, cb_node->activeSubpass, framebuffer); 95485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 95495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9550b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 955183b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis if (!skip_call) { 95524a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdBeginRenderPass(commandBuffer, pRenderPassBegin, contents); 95535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 95545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 95555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 955689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents) { 955783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 955856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 9559b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 95609a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 95615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 95629bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt skip_call |= validatePrimaryCommandBuffer(dev_data, pCB, "vkCmdNextSubpass", VALIDATION_ERROR_00459); 9563baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip_call |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdNextSubpass()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_00457); 956429f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_NEXTSUBPASS, "vkCmdNextSubpass()"); 95651ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_NEXTSUBPASS); 9566ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen skip_call |= outsideRenderPass(dev_data, pCB, "vkCmdNextSubpass()", VALIDATION_ERROR_00458); 956780281691386b37385846f21b38e8c9d4b12cc74eChris Forbes 9568fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes auto subpassCount = pCB->activeRenderPass->createInfo.subpassCount; 956980281691386b37385846f21b38e8c9d4b12cc74eChris Forbes if (pCB->activeSubpass == subpassCount - 1) { 95709bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt skip_call |= log_msg( 95719bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 95729bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt reinterpret_cast<uint64_t>(commandBuffer), __LINE__, VALIDATION_ERROR_00453, "DS", 95739bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "vkCmdNextSubpass(): Attempted to advance beyond final subpass. %s", validation_error_map[VALIDATION_ERROR_00453]); 957480281691386b37385846f21b38e8c9d4b12cc74eChris Forbes } 95755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9576b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 957796ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes 9578cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip_call) return; 957996ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes 95804a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdNextSubpass(commandBuffer, contents); 958196ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes 958296ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes if (pCB) { 9583bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski lock.lock(); 9584bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pCB->activeSubpass++; 9585bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pCB->activeSubpassContents = contents; 958655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski TransitionSubpassLayouts(dev_data, pCB, &pCB->activeRenderPassBeginInfo, pCB->activeSubpass, 95879a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GetFramebufferState(dev_data, pCB->activeRenderPassBeginInfo.framebuffer)); 958896ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes } 95895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 95905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 959189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdEndRenderPass(VkCommandBuffer commandBuffer) { 959283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 959356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 9594b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 95959a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pCB = GetCBNode(dev_data, commandBuffer); 959655867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski FRAMEBUFFER_STATE *framebuffer = NULL; 959758c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes if (pCB) { 9598127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis RENDER_PASS_STATE *rp_state = pCB->activeRenderPass; 95999a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis framebuffer = GetFramebufferState(dev_data, pCB->activeFramebuffer); 9600127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis if (rp_state) { 9601127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis if (pCB->activeSubpass != rp_state->createInfo.subpassCount - 1) { 96029bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt skip_call |= log_msg( 96039bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 96049bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt reinterpret_cast<uint64_t>(commandBuffer), __LINE__, VALIDATION_ERROR_00460, "DS", 96059bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "vkCmdEndRenderPass(): Called before reaching final subpass. %s", validation_error_map[VALIDATION_ERROR_00460]); 960602a3382f28fc7c6ec6018165be88aa6fc4f05c9eChris Forbes } 960702a3382f28fc7c6ec6018165be88aa6fc4f05c9eChris Forbes 9608127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis for (size_t i = 0; i < rp_state->createInfo.attachmentCount; ++i) { 9609e3ad4b1284408353cc56a04951c1df1f35a636ceChris Forbes MT_FB_ATTACHMENT_INFO &fb_info = framebuffer->attachments[i]; 9610127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis auto pAttachment = &rp_state->createInfo.pAttachments[i]; 9611bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (FormatSpecificLoadAndStoreOpSettings(pAttachment->format, pAttachment->storeOp, pAttachment->stencilStoreOp, 9612bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VK_ATTACHMENT_STORE_OP_STORE)) { 961358c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes std::function<bool()> function = [=]() { 96149a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis SetImageMemoryValid(dev_data, GetImageState(dev_data, fb_info.image), true); 961558c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes return false; 961658c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes }; 961758c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes pCB->validate_functions.push_back(function); 9618db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes } else if (FormatSpecificLoadAndStoreOpSettings(pAttachment->format, pAttachment->storeOp, 9619bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pAttachment->stencilStoreOp, VK_ATTACHMENT_STORE_OP_DONT_CARE)) { 962058c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes std::function<bool()> function = [=]() { 96219a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis SetImageMemoryValid(dev_data, GetImageState(dev_data, fb_info.image), false); 962258c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes return false; 962358c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes }; 962458c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes pCB->validate_functions.push_back(function); 96255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 96265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 96275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9628ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen skip_call |= outsideRenderPass(dev_data, pCB, "vkCmdEndRenderpass()", VALIDATION_ERROR_00464); 96299bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt skip_call |= validatePrimaryCommandBuffer(dev_data, pCB, "vkCmdEndRenderPass", VALIDATION_ERROR_00465); 9630baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip_call |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdEndRenderPass()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_00463); 963129f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_ENDRENDERPASS, "vkCmdEndRenderPass()"); 96321ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_ENDRENDERPASS); 96330e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes } 96340e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes lock.unlock(); 96350e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes 9636cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip_call) return; 96370e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes 96384a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdEndRenderPass(commandBuffer); 96390e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes 96400e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes if (pCB) { 96410e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes lock.lock(); 964255867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski TransitionFinalSubpassLayouts(dev_data, pCB, &pCB->activeRenderPassBeginInfo, framebuffer); 964358c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes pCB->activeRenderPass = nullptr; 964458c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes pCB->activeSubpass = 0; 964558c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes pCB->activeFramebuffer = VK_NULL_HANDLE; 96465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 96475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 96485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9649a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlisstatic bool logInvalidAttachmentMessage(layer_data *dev_data, VkCommandBuffer secondaryBuffer, uint32_t primaryAttach, 9650a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis uint32_t secondaryAttach, const char *msg) { 9651df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski return log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 9652df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(secondaryBuffer), __LINE__, VALIDATION_ERROR_02059, "DS", 9653df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "vkCmdExecuteCommands() called w/ invalid Secondary Cmd Buffer 0x%" PRIx64 9654df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski " which has a render pass " 9655df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "that is not compatible with the Primary Cmd Buffer current render pass. " 9656df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "Attachment %u is not compatible with %u: %s. %s", 96579bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt reinterpret_cast<uint64_t &>(secondaryBuffer), primaryAttach, secondaryAttach, msg, 96589bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt validation_error_map[VALIDATION_ERROR_02059]); 96595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 96605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9661a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlisstatic bool validateAttachmentCompatibility(layer_data *dev_data, VkCommandBuffer primaryBuffer, 9662a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis VkRenderPassCreateInfo const *primaryPassCI, uint32_t primaryAttach, 9663a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis VkCommandBuffer secondaryBuffer, VkRenderPassCreateInfo const *secondaryPassCI, 9664e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves uint32_t secondaryAttach, bool is_multi) { 96655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool skip_call = false; 9666a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis if (primaryPassCI->attachmentCount <= primaryAttach) { 96675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis primaryAttach = VK_ATTACHMENT_UNUSED; 96685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9669a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis if (secondaryPassCI->attachmentCount <= secondaryAttach) { 96705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis secondaryAttach = VK_ATTACHMENT_UNUSED; 96715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 96725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (primaryAttach == VK_ATTACHMENT_UNUSED && secondaryAttach == VK_ATTACHMENT_UNUSED) { 96735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return skip_call; 96745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 96755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (primaryAttach == VK_ATTACHMENT_UNUSED) { 9676a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis skip_call |= logInvalidAttachmentMessage(dev_data, secondaryBuffer, primaryAttach, secondaryAttach, 9677a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis "The first is unused while the second is not."); 96785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return skip_call; 96795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 96805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (secondaryAttach == VK_ATTACHMENT_UNUSED) { 9681a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis skip_call |= logInvalidAttachmentMessage(dev_data, secondaryBuffer, primaryAttach, secondaryAttach, 9682a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis "The second is unused while the first is not."); 96835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return skip_call; 96845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9685a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis if (primaryPassCI->pAttachments[primaryAttach].format != secondaryPassCI->pAttachments[secondaryAttach].format) { 9686a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis skip_call |= 9687a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis logInvalidAttachmentMessage(dev_data, secondaryBuffer, primaryAttach, secondaryAttach, "They have different formats."); 96885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9689a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis if (primaryPassCI->pAttachments[primaryAttach].samples != secondaryPassCI->pAttachments[secondaryAttach].samples) { 9690a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis skip_call |= 9691a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis logInvalidAttachmentMessage(dev_data, secondaryBuffer, primaryAttach, secondaryAttach, "They have different samples."); 96925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9693a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis if (is_multi && primaryPassCI->pAttachments[primaryAttach].flags != secondaryPassCI->pAttachments[secondaryAttach].flags) { 9694a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis skip_call |= 9695a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis logInvalidAttachmentMessage(dev_data, secondaryBuffer, primaryAttach, secondaryAttach, "They have different flags."); 96965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 96975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return skip_call; 96985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 96995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9700a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlisstatic bool validateSubpassCompatibility(layer_data *dev_data, VkCommandBuffer primaryBuffer, 9701a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis VkRenderPassCreateInfo const *primaryPassCI, VkCommandBuffer secondaryBuffer, 9702a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis VkRenderPassCreateInfo const *secondaryPassCI, const int subpass, bool is_multi) { 97035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool skip_call = false; 9704a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis const VkSubpassDescription &primary_desc = primaryPassCI->pSubpasses[subpass]; 9705a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis const VkSubpassDescription &secondary_desc = secondaryPassCI->pSubpasses[subpass]; 97065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t maxInputAttachmentCount = std::max(primary_desc.inputAttachmentCount, secondary_desc.inputAttachmentCount); 97075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < maxInputAttachmentCount; ++i) { 97085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t primary_input_attach = VK_ATTACHMENT_UNUSED, secondary_input_attach = VK_ATTACHMENT_UNUSED; 97095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (i < primary_desc.inputAttachmentCount) { 97105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis primary_input_attach = primary_desc.pInputAttachments[i].attachment; 97115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 97125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (i < secondary_desc.inputAttachmentCount) { 97135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis secondary_input_attach = secondary_desc.pInputAttachments[i].attachment; 97145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9715a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis skip_call |= validateAttachmentCompatibility(dev_data, primaryBuffer, primaryPassCI, primary_input_attach, secondaryBuffer, 9716a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis secondaryPassCI, secondary_input_attach, is_multi); 97175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 97185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t maxColorAttachmentCount = std::max(primary_desc.colorAttachmentCount, secondary_desc.colorAttachmentCount); 97195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < maxColorAttachmentCount; ++i) { 97205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t primary_color_attach = VK_ATTACHMENT_UNUSED, secondary_color_attach = VK_ATTACHMENT_UNUSED; 97215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (i < primary_desc.colorAttachmentCount) { 97225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis primary_color_attach = primary_desc.pColorAttachments[i].attachment; 97235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 97245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (i < secondary_desc.colorAttachmentCount) { 97255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis secondary_color_attach = secondary_desc.pColorAttachments[i].attachment; 97265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9727a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis skip_call |= validateAttachmentCompatibility(dev_data, primaryBuffer, primaryPassCI, primary_color_attach, secondaryBuffer, 9728a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis secondaryPassCI, secondary_color_attach, is_multi); 97295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t primary_resolve_attach = VK_ATTACHMENT_UNUSED, secondary_resolve_attach = VK_ATTACHMENT_UNUSED; 97305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (i < primary_desc.colorAttachmentCount && primary_desc.pResolveAttachments) { 97315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis primary_resolve_attach = primary_desc.pResolveAttachments[i].attachment; 97325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 97335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (i < secondary_desc.colorAttachmentCount && secondary_desc.pResolveAttachments) { 97345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis secondary_resolve_attach = secondary_desc.pResolveAttachments[i].attachment; 97355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9736a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis skip_call |= validateAttachmentCompatibility(dev_data, primaryBuffer, primaryPassCI, primary_resolve_attach, 9737a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis secondaryBuffer, secondaryPassCI, secondary_resolve_attach, is_multi); 97385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 97395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t primary_depthstencil_attach = VK_ATTACHMENT_UNUSED, secondary_depthstencil_attach = VK_ATTACHMENT_UNUSED; 97405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (primary_desc.pDepthStencilAttachment) { 97415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis primary_depthstencil_attach = primary_desc.pDepthStencilAttachment[0].attachment; 97425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 97435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (secondary_desc.pDepthStencilAttachment) { 97445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis secondary_depthstencil_attach = secondary_desc.pDepthStencilAttachment[0].attachment; 97455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9746a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis skip_call |= validateAttachmentCompatibility(dev_data, primaryBuffer, primaryPassCI, primary_depthstencil_attach, 9747a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis secondaryBuffer, secondaryPassCI, secondary_depthstencil_attach, is_multi); 97485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return skip_call; 97495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 97505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9751a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis// Verify that given renderPass CreateInfo for primary and secondary command buffers are compatible. 9752a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis// This function deals directly with the CreateInfo, there are overloaded versions below that can take the renderPass handle and 9753a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis// will then feed into this function 9754a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlisstatic bool validateRenderPassCompatibility(layer_data *dev_data, VkCommandBuffer primaryBuffer, 9755a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis VkRenderPassCreateInfo const *primaryPassCI, VkCommandBuffer secondaryBuffer, 9756a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis VkRenderPassCreateInfo const *secondaryPassCI) { 97575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool skip_call = false; 9758a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis 9759a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis if (primaryPassCI->subpassCount != secondaryPassCI->subpassCount) { 9760df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 9761df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(primaryBuffer), __LINE__, DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS", 9762a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis "vkCmdExecuteCommands() called w/ invalid secondary Cmd Buffer 0x%" PRIx64 9763a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis " that has a subpassCount of %u that is incompatible with the primary Cmd Buffer 0x%" PRIx64 9764a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis " that has a subpassCount of %u.", 9765a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis reinterpret_cast<uint64_t &>(secondaryBuffer), secondaryPassCI->subpassCount, 9766a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis reinterpret_cast<uint64_t &>(primaryBuffer), primaryPassCI->subpassCount); 9767a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis } else { 9768a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis for (uint32_t i = 0; i < primaryPassCI->subpassCount; ++i) { 9769a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis skip_call |= validateSubpassCompatibility(dev_data, primaryBuffer, primaryPassCI, secondaryBuffer, secondaryPassCI, i, 9770a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis primaryPassCI->subpassCount > 1); 9771a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis } 97725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 97735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return skip_call; 97745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 97755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9776e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool validateFramebuffer(layer_data *dev_data, VkCommandBuffer primaryBuffer, const GLOBAL_CB_NODE *pCB, 9777e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves VkCommandBuffer secondaryBuffer, const GLOBAL_CB_NODE *pSubCB) { 97785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool skip_call = false; 97795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!pSubCB->beginInfo.pInheritanceInfo) { 97805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return skip_call; 97815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9782c5b97dda856ff837638b3ebb7e231d5507c495a3Chris Forbes VkFramebuffer primary_fb = pCB->activeFramebuffer; 97835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkFramebuffer secondary_fb = pSubCB->beginInfo.pInheritanceInfo->framebuffer; 97845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (secondary_fb != VK_NULL_HANDLE) { 97855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (primary_fb != secondary_fb) { 97869bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt skip_call |= log_msg( 9787df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 9788df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(primaryBuffer), __LINE__, VALIDATION_ERROR_02060, "DS", 97899bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "vkCmdExecuteCommands() called w/ invalid secondary command buffer 0x%" PRIx64 " which has a framebuffer 0x%" PRIx64 97909bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt " that is not the same as the primary command buffer's current active framebuffer 0x%" PRIx64 ". %s", 97919bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt reinterpret_cast<uint64_t &>(secondaryBuffer), reinterpret_cast<uint64_t &>(secondary_fb), 97929bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt reinterpret_cast<uint64_t &>(primary_fb), validation_error_map[VALIDATION_ERROR_02060]); 97935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 97949a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto fb = GetFramebufferState(dev_data, secondary_fb); 9795e3ad4b1284408353cc56a04951c1df1f35a636ceChris Forbes if (!fb) { 9796df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= 9797df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 9798df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(primaryBuffer), __LINE__, DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS", 9799df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "vkCmdExecuteCommands() called w/ invalid Cmd Buffer 0x%p " 9800df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "which has invalid framebuffer 0x%" PRIx64 ".", 9801df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski (void *)secondaryBuffer, (uint64_t)(secondary_fb)); 98025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return skip_call; 98035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 98049a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_renderpass = GetRenderPassState(dev_data, pSubCB->beginInfo.pInheritanceInfo->renderPass); 9805a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis if (cb_renderpass->renderPass != fb->createInfo.renderPass) { 9806a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis skip_call |= validateRenderPassCompatibility(dev_data, secondaryBuffer, fb->renderPassCreateInfo.ptr(), secondaryBuffer, 9807fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes cb_renderpass->createInfo.ptr()); 9808a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis } 98095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 98105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return skip_call; 98115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 98125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9813e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool validateSecondaryCommandBufferState(layer_data *dev_data, GLOBAL_CB_NODE *pCB, GLOBAL_CB_NODE *pSubCB) { 981483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 98155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unordered_set<int> activeTypes; 98165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto queryObject : pCB->activeQueries) { 98175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto queryPoolData = dev_data->queryPoolMap.find(queryObject.pool); 98185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (queryPoolData != dev_data->queryPoolMap.end()) { 98195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (queryPoolData->second.createInfo.queryType == VK_QUERY_TYPE_PIPELINE_STATISTICS && 98205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pSubCB->beginInfo.pInheritanceInfo) { 98215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkQueryPipelineStatisticFlags cmdBufStatistics = pSubCB->beginInfo.pInheritanceInfo->pipelineStatistics; 98225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if ((cmdBufStatistics & queryPoolData->second.createInfo.pipelineStatistics) != cmdBufStatistics) { 9823df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 9824df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 9825df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(pCB->commandBuffer), __LINE__, VALIDATION_ERROR_02065, "DS", 9826cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkCmdExecuteCommands() called w/ invalid Cmd Buffer 0x%p " 9827cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "which has invalid active query pool 0x%" PRIx64 9828cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ". Pipeline statistics is being queried so the command " 9829cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "buffer must have all bits set on the queryPool. %s", 9830cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pCB->commandBuffer, reinterpret_cast<const uint64_t &>(queryPoolData->first), 9831cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski validation_error_map[VALIDATION_ERROR_02065]); 98325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 98335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 98345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis activeTypes.insert(queryPoolData->second.createInfo.queryType); 98355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 98365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 98375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto queryObject : pSubCB->startedQueries) { 98385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto queryPoolData = dev_data->queryPoolMap.find(queryObject.pool); 98395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (queryPoolData != dev_data->queryPoolMap.end() && activeTypes.count(queryPoolData->second.createInfo.queryType)) { 9840df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= 9841df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 9842df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS", 9843df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "vkCmdExecuteCommands() called w/ invalid Cmd Buffer 0x%p " 9844df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "which has invalid active query pool 0x%" PRIx64 9845df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "of type %d but a query of that type has been started on " 9846df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "secondary Cmd Buffer 0x%p.", 9847df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski pCB->commandBuffer, reinterpret_cast<const uint64_t &>(queryPoolData->first), 9848df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski queryPoolData->second.createInfo.queryType, pSubCB->commandBuffer); 98495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 98505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 98517bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski 98529a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto primary_pool = GetCommandPoolNode(dev_data, pCB->createInfo.commandPool); 98539a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto secondary_pool = GetCommandPoolNode(dev_data, pSubCB->createInfo.commandPool); 98547bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski if (primary_pool && secondary_pool && (primary_pool->queueFamilyIndex != secondary_pool->queueFamilyIndex)) { 9855226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis skip_call |= 9856226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 9857226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis reinterpret_cast<uint64_t>(pSubCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_QUEUE_FAMILY, "DS", 9858226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "vkCmdExecuteCommands(): Primary command buffer 0x%p" 9859226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis " created in queue family %d has secondary command buffer 0x%p created in queue family %d.", 9860226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis pCB->commandBuffer, primary_pool->queueFamilyIndex, pSubCB->commandBuffer, secondary_pool->queueFamilyIndex); 98617bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski } 98627bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski 986383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis return skip_call; 98645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 98655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9866bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t commandBuffersCount, 9867bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkCommandBuffer *pCommandBuffers) { 986883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 986956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 9870b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 98719a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 98725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 98735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis GLOBAL_CB_NODE *pSubCB = NULL; 98745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < commandBuffersCount; i++) { 98759a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis pSubCB = GetCBNode(dev_data, pCommandBuffers[i]); 98760a8b955c23012196339f3c10ffedc631ea0f7c58Tobin Ehlis assert(pSubCB); 98770a8b955c23012196339f3c10ffedc631ea0f7c58Tobin Ehlis if (VK_COMMAND_BUFFER_LEVEL_PRIMARY == pSubCB->createInfo.level) { 9878df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip_call |= 9879df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 9880df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(pCommandBuffers[i]), __LINE__, VALIDATION_ERROR_00153, "DS", 9881df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "vkCmdExecuteCommands() called w/ Primary Cmd Buffer 0x%p in element %u of pCommandBuffers " 9882df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "array. All cmd buffers in pCommandBuffers array must be secondary. %s", 9883df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski pCommandBuffers[i], i, validation_error_map[VALIDATION_ERROR_00153]); 9884cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else if (pCB->activeRenderPass) { // Secondary CB w/i RenderPass must have *CONTINUE_BIT set 98859a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto secondary_rp_state = GetRenderPassState(dev_data, pSubCB->beginInfo.pInheritanceInfo->renderPass); 98865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!(pSubCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT)) { 988783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg( 98885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 9889df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(pCommandBuffers[i]), __LINE__, VALIDATION_ERROR_02057, "DS", 9890414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller "vkCmdExecuteCommands(): Secondary Command Buffer (0x%p) executed within render pass (0x%" PRIxLEAST64 98914b6738a6adb4e813d66234defee5d18b7c84340dMike Weiblen ") must have had vkBeginCommandBuffer() called w/ VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT set. %s", 9892226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis pCommandBuffers[i], (uint64_t)pCB->activeRenderPass->renderPass, 98934b6738a6adb4e813d66234defee5d18b7c84340dMike Weiblen validation_error_map[VALIDATION_ERROR_02057]); 98945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 98955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Make sure render pass is compatible with parent command buffer pass if has continue 9896127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis if (pCB->activeRenderPass->renderPass != secondary_rp_state->renderPass) { 9897fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes skip_call |= 9898fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes validateRenderPassCompatibility(dev_data, commandBuffer, pCB->activeRenderPass->createInfo.ptr(), 9899127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis pCommandBuffers[i], secondary_rp_state->createInfo.ptr()); 9900a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis } 99011af6125615cd6dd9735d32e2ee8684abeff28d41Tobin Ehlis // If framebuffer for secondary CB is not NULL, then it must match active FB from primaryCB 990283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= validateFramebuffer(dev_data, commandBuffer, pCB, pCommandBuffers[i], pSubCB); 99035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 99045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis string errorString = ""; 99051af6125615cd6dd9735d32e2ee8684abeff28d41Tobin Ehlis // secondaryCB must have been created w/ RP compatible w/ primaryCB active renderpass 9906127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis if ((pCB->activeRenderPass->renderPass != secondary_rp_state->renderPass) && 9907fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes !verify_renderpass_compatibility(dev_data, pCB->activeRenderPass->createInfo.ptr(), 9908127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis secondary_rp_state->createInfo.ptr(), errorString)) { 990983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg( 99105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 9911df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(pCommandBuffers[i]), __LINE__, DRAWSTATE_RENDERPASS_INCOMPATIBLE, "DS", 9912414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller "vkCmdExecuteCommands(): Secondary Command Buffer (0x%p) w/ render pass (0x%" PRIxLEAST64 9913414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller ") is incompatible w/ primary command buffer (0x%p) w/ render pass (0x%" PRIxLEAST64 ") due to: %s", 9914226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis pCommandBuffers[i], (uint64_t)pSubCB->beginInfo.pInheritanceInfo->renderPass, commandBuffer, 9915ee691f5c5fa87aac3750454d2bca2cb582e4e817Chris Forbes (uint64_t)pCB->activeRenderPass->renderPass, errorString.c_str()); 99165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 99175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 99185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODO(mlentine): Move more logic into this method 991983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= validateSecondaryCommandBufferState(dev_data, pCB, pSubCB); 992051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour skip_call |= validateCommandBufferState(dev_data, pSubCB, "vkCmdExecuteCommands()", 0); 99215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Secondary cmdBuffers are considered pending execution starting w/ 99225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // being recorded 99235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!(pSubCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT)) { 99245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (dev_data->globalInFlightCmdBuffers.find(pSubCB->commandBuffer) != dev_data->globalInFlightCmdBuffers.end()) { 9925cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 9926df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 9927df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(pCB->commandBuffer), __LINE__, VALIDATION_ERROR_00154, "DS", 9928cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Attempt to simultaneously execute command buffer 0x%p" 9929cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " without VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT set! %s", 9930cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pCB->commandBuffer, validation_error_map[VALIDATION_ERROR_00154]); 99315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 99325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT) { 99335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Warn that non-simultaneous secondary cmd buffer renders primary non-simultaneous 993483b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg( 99355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 9936df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(pCommandBuffers[i]), __LINE__, DRAWSTATE_INVALID_CB_SIMULTANEOUS_USE, "DS", 9937226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "vkCmdExecuteCommands(): Secondary Command Buffer (0x%p) " 9938226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "does not have VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT set and will cause primary command buffer " 9939226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "(0x%p) to be treated as if it does not have VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT " 994083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis "set, even though it does.", 9941226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis pCommandBuffers[i], pCB->commandBuffer); 99425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->beginInfo.flags &= ~VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT; 99435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 99445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9945f71dd305f197826a61f398bff725267a20ea1d90Chris Forbes if (!pCB->activeQueries.empty() && !dev_data->enabled_features.inheritedQueries) { 9946cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski skip_call |= 9947cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 9948cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski reinterpret_cast<uint64_t>(pCommandBuffers[i]), __LINE__, VALIDATION_ERROR_02062, "DS", 9949cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkCmdExecuteCommands(): Secondary Command Buffer " 9950cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "(0x%p) cannot be submitted with a query in " 9951cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "flight and inherited queries not " 9952cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "supported on this device. %s", 9953cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pCommandBuffers[i], validation_error_map[VALIDATION_ERROR_02062]); 99545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 99558567fecbf563420f5900ade277ca68908aa87259Tobin Ehlis // Propagate layout transitions to the primary cmd buffer 99568567fecbf563420f5900ade277ca68908aa87259Tobin Ehlis for (auto ilm_entry : pSubCB->imageLayoutMap) { 995755867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski SetLayout(dev_data, pCB, ilm_entry.first, ilm_entry.second); 99588567fecbf563420f5900ade277ca68908aa87259Tobin Ehlis } 99595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pSubCB->primaryCommandBuffer = pCB->commandBuffer; 99605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->secondaryCommandBuffers.insert(pSubCB->commandBuffer); 99615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->globalInFlightCmdBuffers.insert(pSubCB->commandBuffer); 9962d4ee9fdb2def1e9dc70c5627c9103e264471b8ebMichael Lentine for (auto &function : pSubCB->queryUpdates) { 9963d4ee9fdb2def1e9dc70c5627c9103e264471b8ebMichael Lentine pCB->queryUpdates.push_back(function); 9964d4ee9fdb2def1e9dc70c5627c9103e264471b8ebMichael Lentine } 99655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 99669bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt skip_call |= validatePrimaryCommandBuffer(dev_data, pCB, "vkCmdExecuteComands", VALIDATION_ERROR_00163); 9967baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip_call |= 9968baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt ValidateCmdQueueFlags(dev_data, pCB, "vkCmdExecuteComands()", 9969baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt VK_QUEUE_TRANSFER_BIT | VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, VALIDATION_ERROR_00162); 997029f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip_call |= ValidateCmd(dev_data, pCB, CMD_EXECUTECOMMANDS, "vkCmdExecuteComands()"); 99711ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_EXECUTECOMMANDS); 99725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9973b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 9974cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.CmdExecuteCommands(commandBuffer, commandBuffersCount, pCommandBuffers); 99755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 99765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9977bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL MapMemory(VkDevice device, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size, VkFlags flags, 9978bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski void **ppData) { 997956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 99805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9981e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool skip_call = false; 99825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 9983b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 99849a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *mem_info = GetMemObjInfo(dev_data, mem); 9985cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis if (mem_info) { 9986f541bf53dee6daf82a4c8304354eac599a884d29Tobin Ehlis // TODO : This could me more fine-grained to track just region that is valid 9987f541bf53dee6daf82a4c8304354eac599a884d29Tobin Ehlis mem_info->global_valid = true; 9988623548a271287ae55415e45e3c654ee66d4e79ffTobin Ehlis auto end_offset = (VK_WHOLE_SIZE == size) ? mem_info->alloc_info.allocationSize - 1 : offset + size - 1; 9989c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinski skip_call |= ValidateMapImageLayouts(dev_data, device, mem_info, offset, end_offset); 9990cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis // TODO : Do we need to create new "bound_range" for the mapped range? 9991623548a271287ae55415e45e3c654ee66d4e79ffTobin Ehlis SetMemRangesValid(dev_data, mem_info, offset, end_offset); 9992cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis if ((dev_data->phys_dev_mem_props.memoryTypes[mem_info->alloc_info.memoryTypeIndex].propertyFlags & 9993b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0) { 99942fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen skip_call = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 99952fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen (uint64_t)mem, __LINE__, VALIDATION_ERROR_00629, "MEM", 99962fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen "Mapping Memory without VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT set: mem obj 0x%" PRIxLEAST64 ". %s", 99972fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen (uint64_t)mem, validation_error_map[VALIDATION_ERROR_00629]); 99985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 99995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 10000f57fc64ac43691ad98e1713886b345465573070aTobin Ehlis skip_call |= ValidateMapMemRange(dev_data, mem, offset, size); 10001b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 100025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10003e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves if (!skip_call) { 100044a0754042cf090e131e9e769d8a3633c228625beChris Forbes result = dev_data->dispatch_table.MapMemory(device, mem, offset, size, flags, ppData); 100057c0012acb5327961b0a5191434a08e5fa788786dTobin Ehlis if (VK_SUCCESS == result) { 100067c0012acb5327961b0a5191434a08e5fa788786dTobin Ehlis lock.lock(); 10007cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis // TODO : What's the point of this range? See comment on creating new "bound_range" above, which may replace this 100087c0012acb5327961b0a5191434a08e5fa788786dTobin Ehlis storeMemRanges(dev_data, mem, offset, size); 100095f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski initializeAndTrackMemory(dev_data, mem, offset, size, ppData); 100107c0012acb5327961b0a5191434a08e5fa788786dTobin Ehlis lock.unlock(); 100117c0012acb5327961b0a5191434a08e5fa788786dTobin Ehlis } 100125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 100135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 100145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 100155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1001689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL UnmapMemory(VkDevice device, VkDeviceMemory mem) { 1001756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 1001883b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 100195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10020b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 100218860b85a52096f9f9b28616bc37feed505497a54Chris Forbes skip_call |= deleteMemRanges(dev_data, mem); 10022b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 1002383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis if (!skip_call) { 100244a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.UnmapMemory(device, mem); 100255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 100265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 100275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 100288860b85a52096f9f9b28616bc37feed505497a54Chris Forbesstatic bool validateMemoryIsMapped(layer_data *dev_data, const char *funcName, uint32_t memRangeCount, 10029e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves const VkMappedMemoryRange *pMemRanges) { 10030c7ee6f2fe100c1aacfaa0872832717c906bb8a4aMark Lobodzinski bool skip = false; 100315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < memRangeCount; ++i) { 100329a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto mem_info = GetMemObjInfo(dev_data, pMemRanges[i].memory); 1003357fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis if (mem_info) { 10034f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski if (pMemRanges[i].size == VK_WHOLE_SIZE) { 10035f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski if (mem_info->mem_range.offset > pMemRanges[i].offset) { 10036cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 10037cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, (uint64_t)pMemRanges[i].memory, __LINE__, 10038cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VALIDATION_ERROR_00643, "MEM", "%s: Flush/Invalidate offset (" PRINTF_SIZE_T_SPECIFIER 10039cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ") is less than Memory Object's offset " 10040cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "(" PRINTF_SIZE_T_SPECIFIER "). %s", 10041cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski funcName, static_cast<size_t>(pMemRanges[i].offset), 10042cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski static_cast<size_t>(mem_info->mem_range.offset), validation_error_map[VALIDATION_ERROR_00643]); 10043f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski } 10044f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski } else { 10045f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski const uint64_t data_end = (mem_info->mem_range.size == VK_WHOLE_SIZE) 10046f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski ? mem_info->alloc_info.allocationSize 10047f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski : (mem_info->mem_range.offset + mem_info->mem_range.size); 10048f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski if ((mem_info->mem_range.offset > pMemRanges[i].offset) || 10049f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski (data_end < (pMemRanges[i].offset + pMemRanges[i].size))) { 10050c7ee6f2fe100c1aacfaa0872832717c906bb8a4aMark Lobodzinski skip |= 10051f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 10052f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski (uint64_t)pMemRanges[i].memory, __LINE__, VALIDATION_ERROR_00642, "MEM", 10053f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski "%s: Flush/Invalidate size or offset (" PRINTF_SIZE_T_SPECIFIER ", " PRINTF_SIZE_T_SPECIFIER 10054f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski ") exceed the Memory Object's upper-bound " 10055f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski "(" PRINTF_SIZE_T_SPECIFIER "). %s", 10056f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski funcName, static_cast<size_t>(pMemRanges[i].offset + pMemRanges[i].size), 10057f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski static_cast<size_t>(pMemRanges[i].offset), static_cast<size_t>(data_end), 10058f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski validation_error_map[VALIDATION_ERROR_00642]); 10059f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski } 100605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 100615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 100625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 10063c7ee6f2fe100c1aacfaa0872832717c906bb8a4aMark Lobodzinski return skip; 100645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 100655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10066bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinskistatic bool ValidateAndCopyNoncoherentMemoryToDriver(layer_data *dev_data, uint32_t mem_range_count, 10067bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski const VkMappedMemoryRange *mem_ranges) { 10068bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski bool skip = false; 10069bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski for (uint32_t i = 0; i < mem_range_count; ++i) { 100709a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto mem_info = GetMemObjInfo(dev_data, mem_ranges[i].memory); 1007157fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis if (mem_info) { 100725f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski if (mem_info->shadow_copy) { 100735f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski VkDeviceSize size = (mem_info->mem_range.size != VK_WHOLE_SIZE) 100745f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski ? mem_info->mem_range.size 10075d8a53ade6b5501256798a8b4ec0bc14f72adc1faTobin Ehlis : (mem_info->alloc_info.allocationSize - mem_info->mem_range.offset); 100765f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski char *data = static_cast<char *>(mem_info->shadow_copy); 100775f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski for (uint64_t j = 0; j < mem_info->shadow_pad_size; ++j) { 100785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (data[j] != NoncoherentMemoryFillValue) { 10079bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 10080bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, (uint64_t)mem_ranges[i].memory, __LINE__, 10081bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski MEMTRACK_INVALID_MAP, "MEM", "Memory underflow was detected on mem obj 0x%" PRIxLEAST64, 10082bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski (uint64_t)mem_ranges[i].memory); 100835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 100845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 100855f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski for (uint64_t j = (size + mem_info->shadow_pad_size); j < (2 * mem_info->shadow_pad_size + size); ++j) { 100865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (data[j] != NoncoherentMemoryFillValue) { 10087bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 10088bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, (uint64_t)mem_ranges[i].memory, __LINE__, 10089bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski MEMTRACK_INVALID_MAP, "MEM", "Memory overflow was detected on mem obj 0x%" PRIxLEAST64, 10090bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski (uint64_t)mem_ranges[i].memory); 100915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 100925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 100935f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski memcpy(mem_info->p_driver_data, static_cast<void *>(data + mem_info->shadow_pad_size), (size_t)(size)); 100945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 100955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 100965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 10097bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski return skip; 100985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 100995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10100bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinskistatic void CopyNoncoherentMemoryFromDriver(layer_data *dev_data, uint32_t mem_range_count, const VkMappedMemoryRange *mem_ranges) { 10101bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski for (uint32_t i = 0; i < mem_range_count; ++i) { 101029a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto mem_info = GetMemObjInfo(dev_data, mem_ranges[i].memory); 101035f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski if (mem_info && mem_info->shadow_copy) { 101045f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski VkDeviceSize size = (mem_info->mem_range.size != VK_WHOLE_SIZE) 101055f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski ? mem_info->mem_range.size 101065f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski : (mem_info->alloc_info.allocationSize - mem_ranges[i].offset); 101075f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski char *data = static_cast<char *>(mem_info->shadow_copy); 101085f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski memcpy(data + mem_info->shadow_pad_size, mem_info->p_driver_data, (size_t)(size)); 101099e21e56fc23ade48efd3752d2e2729895eb90349Mark Lobodzinski } 101109e21e56fc23ade48efd3752d2e2729895eb90349Mark Lobodzinski } 101119e21e56fc23ade48efd3752d2e2729895eb90349Mark Lobodzinski} 101129e21e56fc23ade48efd3752d2e2729895eb90349Mark Lobodzinski 10113ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinskistatic bool ValidateMappedMemoryRangeDeviceLimits(layer_data *dev_data, const char *func_name, uint32_t mem_range_count, 10114ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski const VkMappedMemoryRange *mem_ranges) { 10115ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski bool skip = false; 10116ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski for (uint32_t i = 0; i < mem_range_count; ++i) { 10117ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski uint64_t atom_size = dev_data->phys_dev_properties.properties.limits.nonCoherentAtomSize; 10118ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski if (vk_safe_modulo(mem_ranges[i].offset, atom_size) != 0) { 10119df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 10120df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<const uint64_t &>(mem_ranges->memory), __LINE__, VALIDATION_ERROR_00644, "MEM", 10121ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski "%s: Offset in pMemRanges[%d] is 0x%" PRIxLEAST64 10122ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski ", which is not a multiple of VkPhysicalDeviceLimits::nonCoherentAtomSize (0x%" PRIxLEAST64 "). %s", 10123ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski func_name, i, mem_ranges[i].offset, atom_size, validation_error_map[VALIDATION_ERROR_00644]); 10124ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski } 10125ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski if ((mem_ranges[i].size != VK_WHOLE_SIZE) && (vk_safe_modulo(mem_ranges[i].size, atom_size) != 0)) { 10126df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 10127df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<const uint64_t &>(mem_ranges->memory), __LINE__, VALIDATION_ERROR_00645, "MEM", 10128ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski "%s: Size in pMemRanges[%d] is 0x%" PRIxLEAST64 10129ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski ", which is not a multiple of VkPhysicalDeviceLimits::nonCoherentAtomSize (0x%" PRIxLEAST64 "). %s", 10130ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski func_name, i, mem_ranges[i].size, atom_size, validation_error_map[VALIDATION_ERROR_00645]); 10131ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski } 10132ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski } 10133ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski return skip; 10134ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski} 10135ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski 1013680e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinskistatic bool PreCallValidateFlushMappedMemoryRanges(layer_data *dev_data, uint32_t mem_range_count, 1013780e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski const VkMappedMemoryRange *mem_ranges) { 1013880e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski bool skip = false; 1013980e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski std::lock_guard<std::mutex> lock(global_lock); 1014080e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski skip |= ValidateAndCopyNoncoherentMemoryToDriver(dev_data, mem_range_count, mem_ranges); 1014180e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski skip |= validateMemoryIsMapped(dev_data, "vkFlushMappedMemoryRanges", mem_range_count, mem_ranges); 1014280e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski return skip; 1014380e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski} 1014480e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski 10145bba0de708d942e9a2187158915856995db1c5a4dMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL FlushMappedMemoryRanges(VkDevice device, uint32_t memRangeCount, 10146bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski const VkMappedMemoryRange *pMemRanges) { 101475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 1014856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 101495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1015080e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski if (!PreCallValidateFlushMappedMemoryRanges(dev_data, memRangeCount, pMemRanges)) { 101514a0754042cf090e131e9e769d8a3633c228625beChris Forbes result = dev_data->dispatch_table.FlushMappedMemoryRanges(device, memRangeCount, pMemRanges); 101525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 101535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 101545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 101555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1015680e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinskistatic bool PreCallValidateInvalidateMappedMemoryRanges(layer_data *dev_data, uint32_t mem_range_count, 1015780e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski const VkMappedMemoryRange *mem_ranges) { 1015880e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski bool skip = false; 1015980e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski std::lock_guard<std::mutex> lock(global_lock); 1016080e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski skip |= validateMemoryIsMapped(dev_data, "vkInvalidateMappedMemoryRanges", mem_range_count, mem_ranges); 1016180e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski return skip; 1016280e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski} 1016380e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski 1016480e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinskistatic void PostCallRecordInvalidateMappedMemoryRanges(layer_data *dev_data, uint32_t mem_range_count, 1016580e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski const VkMappedMemoryRange *mem_ranges) { 1016680e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski std::lock_guard<std::mutex> lock(global_lock); 1016780e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski // Update our shadow copy with modified driver data 1016880e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski CopyNoncoherentMemoryFromDriver(dev_data, mem_range_count, mem_ranges); 1016980e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski} 1017080e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski 10171bba0de708d942e9a2187158915856995db1c5a4dMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL InvalidateMappedMemoryRanges(VkDevice device, uint32_t memRangeCount, 10172bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski const VkMappedMemoryRange *pMemRanges) { 101735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 1017456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 101755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1017680e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski if (!PreCallValidateInvalidateMappedMemoryRanges(dev_data, memRangeCount, pMemRanges)) { 101774a0754042cf090e131e9e769d8a3633c228625beChris Forbes result = dev_data->dispatch_table.InvalidateMappedMemoryRanges(device, memRangeCount, pMemRanges); 1017880e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski if (result == VK_SUCCESS) { 1017980e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski PostCallRecordInvalidateMappedMemoryRanges(dev_data, memRangeCount, pMemRanges); 1018080e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski } 101815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 101825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 101835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 101845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10185160335c453ec51cc48bdef78e8befdb3c86ff292Cort Strattonstatic bool PreCallValidateBindImageMemory(layer_data *dev_data, VkImage image, IMAGE_STATE *image_state, VkDeviceMemory mem, 10186160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton VkDeviceSize memoryOffset) { 101870109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski bool skip = false; 101881facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis if (image_state) { 10189160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton std::unique_lock<std::mutex> lock(global_lock); 1019094c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis // Track objects tied to memory 1019147aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski uint64_t image_handle = reinterpret_cast<uint64_t &>(image); 10192c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton skip = ValidateSetMemBinding(dev_data, mem, image_handle, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, "vkBindImageMemory()"); 10193ff3ef1181960319d2268e82dae075726f650c553Tobin Ehlis if (!image_state->memory_requirements_checked) { 10194ff3ef1181960319d2268e82dae075726f650c553Tobin Ehlis // There's not an explicit requirement in the spec to call vkGetImageMemoryRequirements() prior to calling 10195341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton // BindImageMemory but it's implied in that memory being bound must conform with VkMemoryRequirements from 10196341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton // vkGetImageMemoryRequirements() 101970109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 101980109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski image_handle, __LINE__, DRAWSTATE_INVALID_IMAGE, "DS", 101990109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski "vkBindImageMemory(): Binding memory to image 0x%" PRIxLEAST64 102000109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski " but vkGetImageMemoryRequirements() has not been called on that image.", 102010109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski image_handle); 10202ff3ef1181960319d2268e82dae075726f650c553Tobin Ehlis // Make the call for them so we can verify the state 10203ff3ef1181960319d2268e82dae075726f650c553Tobin Ehlis lock.unlock(); 10204341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton dev_data->dispatch_table.GetImageMemoryRequirements(dev_data->device, image, &image_state->requirements); 10205ff3ef1181960319d2268e82dae075726f650c553Tobin Ehlis lock.lock(); 10206ff3ef1181960319d2268e82dae075726f650c553Tobin Ehlis } 1020747aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski 102080ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton // Validate bound memory range information 102099a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto mem_info = GetMemObjInfo(dev_data, mem); 1021057fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis if (mem_info) { 102110ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton skip |= ValidateInsertImageMemoryRange(dev_data, image, mem_info, memoryOffset, image_state->requirements, 102120ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton image_state->createInfo.tiling == VK_IMAGE_TILING_LINEAR, "vkBindImageMemory()"); 1021374300755ed9ec780d6073af71e47f201217008d6Cort Stratton skip |= ValidateMemoryTypes(dev_data, mem_info, image_state->requirements.memoryTypeBits, "vkBindImageMemory()", 102140109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski VALIDATION_ERROR_00806); 1021547aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski } 10216160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton 10217160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton // Validate memory requirements alignment 10218160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton if (vk_safe_modulo(memoryOffset, image_state->requirements.alignment) != 0) { 10219160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 10220160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton image_handle, __LINE__, VALIDATION_ERROR_02178, "DS", 10221160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton "vkBindImageMemory(): memoryOffset is 0x%" PRIxLEAST64 10222160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton " but must be an integer multiple of the " 10223160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton "VkMemoryRequirements::alignment value 0x%" PRIxLEAST64 10224160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton ", returned from a call to vkGetImageMemoryRequirements with image. %s", 10225160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton memoryOffset, image_state->requirements.alignment, validation_error_map[VALIDATION_ERROR_02178]); 10226160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton } 10227160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton 10228160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton // Validate memory requirements size 10229160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton if (image_state->requirements.size > mem_info->alloc_info.allocationSize - memoryOffset) { 10230160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 10231160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton image_handle, __LINE__, VALIDATION_ERROR_02179, "DS", 10232160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton "vkBindImageMemory(): memory size minus memoryOffset is 0x%" PRIxLEAST64 10233160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton " but must be at least as large as " 10234160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton "VkMemoryRequirements::size value 0x%" PRIxLEAST64 10235160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton ", returned from a call to vkGetImageMemoryRequirements with image. %s", 10236160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton mem_info->alloc_info.allocationSize - memoryOffset, image_state->requirements.size, 10237160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton validation_error_map[VALIDATION_ERROR_02179]); 10238160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton } 10239341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton } 10240341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton return skip; 10241341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton} 1024247aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski 10243160335c453ec51cc48bdef78e8befdb3c86ff292Cort Strattonstatic void PostCallRecordBindImageMemory(layer_data *dev_data, VkImage image, IMAGE_STATE *image_state, VkDeviceMemory mem, 10244160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton VkDeviceSize memoryOffset) { 10245341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton if (image_state) { 10246160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton std::unique_lock<std::mutex> lock(global_lock); 102470ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton // Track bound memory range information 102480ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton auto mem_info = GetMemObjInfo(dev_data, mem); 102490ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton if (mem_info) { 102500ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton InsertImageMemoryRange(dev_data, image, mem_info, memoryOffset, image_state->requirements, 102510ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton image_state->createInfo.tiling == VK_IMAGE_TILING_LINEAR); 102520ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton } 102530ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton 10254c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton // Track objects tied to memory 10255c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton uint64_t image_handle = reinterpret_cast<uint64_t &>(image); 10256c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton SetMemBinding(dev_data, mem, image_handle, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, "vkBindImageMemory()"); 10257c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton 10258341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton image_state->binding.mem = mem; 10259341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton image_state->binding.offset = memoryOffset; 10260341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton image_state->binding.size = image_state->requirements.size; 10261341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton } 10262341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton} 10263341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton 10264341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort StrattonVKAPI_ATTR VkResult VKAPI_CALL BindImageMemory(VkDevice device, VkImage image, VkDeviceMemory mem, VkDeviceSize memoryOffset) { 10265341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 10266341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 10267160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton auto image_state = GetImageState(dev_data, image); 10268160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton bool skip = PreCallValidateBindImageMemory(dev_data, image, image_state, mem, memoryOffset); 10269341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton if (!skip) { 10270341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton result = dev_data->dispatch_table.BindImageMemory(device, image, mem, memoryOffset); 10271341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton if (result == VK_SUCCESS) { 10272160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton PostCallRecordBindImageMemory(dev_data, image, image_state, mem, memoryOffset); 1027394c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis } 102745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 102755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 102765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 102775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1027889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL SetEvent(VkDevice device, VkEvent event) { 102793ee1d6057ee6c49b9dbbeb067b7fd149bdba7b5cTobin Ehlis bool skip_call = false; 102803ee1d6057ee6c49b9dbbeb067b7fd149bdba7b5cTobin Ehlis VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 1028156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 10282b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 102839a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto event_state = GetEventNode(dev_data, event); 102844710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis if (event_state) { 102854710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis event_state->needsSignaled = false; 102864710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis event_state->stageMask = VK_PIPELINE_STAGE_HOST_BIT; 102874710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis if (event_state->write_in_use) { 102883ee1d6057ee6c49b9dbbeb067b7fd149bdba7b5cTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT, 102893ee1d6057ee6c49b9dbbeb067b7fd149bdba7b5cTobin Ehlis reinterpret_cast<const uint64_t &>(event), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS", 10290414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller "Cannot call vkSetEvent() on event 0x%" PRIxLEAST64 " that is already in use by a command buffer.", 102913ee1d6057ee6c49b9dbbeb067b7fd149bdba7b5cTobin Ehlis reinterpret_cast<const uint64_t &>(event)); 102923ee1d6057ee6c49b9dbbeb067b7fd149bdba7b5cTobin Ehlis } 102933ee1d6057ee6c49b9dbbeb067b7fd149bdba7b5cTobin Ehlis } 10294b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 102956fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis // Host setting event is visible to all queues immediately so update stageMask for any queue that's seen this event 102966fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis // TODO : For correctness this needs separate fix to verify that app doesn't make incorrect assumptions about the 102976fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis // ordering of this command in relation to vkCmd[Set|Reset]Events (see GH297) 102986fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis for (auto queue_data : dev_data->queueMap) { 102996fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis auto event_entry = queue_data.second.eventToStageMap.find(event); 103006fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis if (event_entry != queue_data.second.eventToStageMap.end()) { 103016fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis event_entry->second |= VK_PIPELINE_STAGE_HOST_BIT; 103026fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis } 103036fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis } 10304cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) result = dev_data->dispatch_table.SetEvent(device, event); 103055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 103065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 103075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10308bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL QueueBindSparse(VkQueue queue, uint32_t bindInfoCount, const VkBindSparseInfo *pBindInfo, 10309bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkFence fence) { 1031056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map); 103115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 10312e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool skip_call = false; 10313b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 103149a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pFence = GetFenceNode(dev_data, fence); 103159a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pQueue = GetQueueState(dev_data, queue); 10316651d92815dfff917308137bb67aacccc4f60df86Chris Forbes 103174b38d3aa8b6be6a7f5bebb472ab439da0562824fTobin Ehlis // First verify that fence is not in use 10318651d92815dfff917308137bb67aacccc4f60df86Chris Forbes skip_call |= ValidateFenceForSubmit(dev_data, pFence); 10319651d92815dfff917308137bb67aacccc4f60df86Chris Forbes 103209867daedbf52debc77d6568162ee21e071699b80Chris Forbes if (pFence) { 1032193ccd9708dad3ffb58a3fc09a3d61cc5fe1569f8Mark Lobodzinski SubmitFence(pQueue, pFence, std::max(1u, bindInfoCount)); 103224b38d3aa8b6be6a7f5bebb472ab439da0562824fTobin Ehlis } 10323651d92815dfff917308137bb67aacccc4f60df86Chris Forbes 103241344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis for (uint32_t bindIdx = 0; bindIdx < bindInfoCount; ++bindIdx) { 103251344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis const VkBindSparseInfo &bindInfo = pBindInfo[bindIdx]; 103265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Track objects tied to memory 103271344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis for (uint32_t j = 0; j < bindInfo.bufferBindCount; j++) { 103281344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis for (uint32_t k = 0; k < bindInfo.pBufferBinds[j].bindCount; k++) { 10329f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis auto sparse_binding = bindInfo.pBufferBinds[j].pBinds[k]; 10330f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis if (SetSparseMemBinding(dev_data, {sparse_binding.memory, sparse_binding.memoryOffset, sparse_binding.size}, 10331f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis (uint64_t)bindInfo.pBufferBinds[j].buffer, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, 10332f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis "vkQueueBindSparse")) 10333e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves skip_call = true; 103345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 103355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 103361344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis for (uint32_t j = 0; j < bindInfo.imageOpaqueBindCount; j++) { 103371344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis for (uint32_t k = 0; k < bindInfo.pImageOpaqueBinds[j].bindCount; k++) { 10338f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis auto sparse_binding = bindInfo.pImageOpaqueBinds[j].pBinds[k]; 10339f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis if (SetSparseMemBinding(dev_data, {sparse_binding.memory, sparse_binding.memoryOffset, sparse_binding.size}, 10340f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis (uint64_t)bindInfo.pImageOpaqueBinds[j].image, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 10341f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis "vkQueueBindSparse")) 10342e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves skip_call = true; 103435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 103445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 103451344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis for (uint32_t j = 0; j < bindInfo.imageBindCount; j++) { 103461344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis for (uint32_t k = 0; k < bindInfo.pImageBinds[j].bindCount; k++) { 10347f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis auto sparse_binding = bindInfo.pImageBinds[j].pBinds[k]; 10348f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis // TODO: This size is broken for non-opaque bindings, need to update to comprehend full sparse binding data 10349f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis VkDeviceSize size = sparse_binding.extent.depth * sparse_binding.extent.height * sparse_binding.extent.width * 4; 10350f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis if (SetSparseMemBinding(dev_data, {sparse_binding.memory, sparse_binding.memoryOffset, size}, 10351f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis (uint64_t)bindInfo.pImageBinds[j].image, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 10352f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis "vkQueueBindSparse")) 10353e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves skip_call = true; 103545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 103555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 103569867daedbf52debc77d6568162ee21e071699b80Chris Forbes 103579867daedbf52debc77d6568162ee21e071699b80Chris Forbes std::vector<SEMAPHORE_WAIT> semaphore_waits; 103589867daedbf52debc77d6568162ee21e071699b80Chris Forbes std::vector<VkSemaphore> semaphore_signals; 103591344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis for (uint32_t i = 0; i < bindInfo.waitSemaphoreCount; ++i) { 1036001a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes VkSemaphore semaphore = bindInfo.pWaitSemaphores[i]; 103619a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pSemaphore = GetSemaphoreNode(dev_data, semaphore); 1036201a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes if (pSemaphore) { 1036301a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes if (pSemaphore->signaled) { 103649867daedbf52debc77d6568162ee21e071699b80Chris Forbes if (pSemaphore->signaler.first != VK_NULL_HANDLE) { 103659867daedbf52debc77d6568162ee21e071699b80Chris Forbes semaphore_waits.push_back({semaphore, pSemaphore->signaler.first, pSemaphore->signaler.second}); 103669867daedbf52debc77d6568162ee21e071699b80Chris Forbes pSemaphore->in_use.fetch_add(1); 103679867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 103689867daedbf52debc77d6568162ee21e071699b80Chris Forbes pSemaphore->signaler.first = VK_NULL_HANDLE; 1036901a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes pSemaphore->signaled = false; 103701344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis } else { 10371226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis skip_call |= log_msg( 10372226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT, 10373226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis reinterpret_cast<const uint64_t &>(semaphore), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS", 10374226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "vkQueueBindSparse: Queue 0x%p is waiting on semaphore 0x%" PRIx64 " that has no way to be signaled.", 10375226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis queue, reinterpret_cast<const uint64_t &>(semaphore)); 103765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 103775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 103785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 103791344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis for (uint32_t i = 0; i < bindInfo.signalSemaphoreCount; ++i) { 1038001a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes VkSemaphore semaphore = bindInfo.pSignalSemaphores[i]; 103819a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pSemaphore = GetSemaphoreNode(dev_data, semaphore); 1038201a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes if (pSemaphore) { 1038301a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes if (pSemaphore->signaled) { 103845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis skip_call = 103855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT, 103861344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis reinterpret_cast<const uint64_t &>(semaphore), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS", 10387226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "vkQueueBindSparse: Queue 0x%p is signaling semaphore 0x%" PRIx64 103881344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis ", but that semaphore is already signaled.", 10389226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis queue, reinterpret_cast<const uint64_t &>(semaphore)); 10390bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski } else { 103919867daedbf52debc77d6568162ee21e071699b80Chris Forbes pSemaphore->signaler.first = queue; 103929867daedbf52debc77d6568162ee21e071699b80Chris Forbes pSemaphore->signaler.second = pQueue->seq + pQueue->submissions.size() + 1; 103939867daedbf52debc77d6568162ee21e071699b80Chris Forbes pSemaphore->signaled = true; 103949867daedbf52debc77d6568162ee21e071699b80Chris Forbes pSemaphore->in_use.fetch_add(1); 103959867daedbf52debc77d6568162ee21e071699b80Chris Forbes semaphore_signals.push_back(semaphore); 103969867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 103975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 103985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 103999867daedbf52debc77d6568162ee21e071699b80Chris Forbes 10400bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pQueue->submissions.emplace_back(std::vector<VkCommandBuffer>(), semaphore_waits, semaphore_signals, 104019867daedbf52debc77d6568162ee21e071699b80Chris Forbes bindIdx == bindInfoCount - 1 ? fence : VK_NULL_HANDLE); 104025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 104039867daedbf52debc77d6568162ee21e071699b80Chris Forbes 104049867daedbf52debc77d6568162ee21e071699b80Chris Forbes if (pFence && !bindInfoCount) { 104059867daedbf52debc77d6568162ee21e071699b80Chris Forbes // No work to do, just dropping a fence in the queue by itself. 10406bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pQueue->submissions.emplace_back(std::vector<VkCommandBuffer>(), std::vector<SEMAPHORE_WAIT>(), std::vector<VkSemaphore>(), 104079867daedbf52debc77d6568162ee21e071699b80Chris Forbes fence); 104089867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 104099867daedbf52debc77d6568162ee21e071699b80Chris Forbes 10410b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 104115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10412cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) return dev_data->dispatch_table.QueueBindSparse(queue, bindInfoCount, pBindInfo, fence); 104135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 104145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 104155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 104165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1041789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateSemaphore(VkDevice device, const VkSemaphoreCreateInfo *pCreateInfo, 1041889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkSemaphore *pSemaphore) { 1041956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 104204a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateSemaphore(device, pCreateInfo, pAllocator, pSemaphore); 104215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (result == VK_SUCCESS) { 10422b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 10423bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SEMAPHORE_NODE *sNode = &dev_data->semaphoreMap[*pSemaphore]; 104249867daedbf52debc77d6568162ee21e071699b80Chris Forbes sNode->signaler.first = VK_NULL_HANDLE; 104259867daedbf52debc77d6568162ee21e071699b80Chris Forbes sNode->signaler.second = 0; 104261344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis sNode->signaled = false; 104275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 104285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 104295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 104305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10431bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateEvent(VkDevice device, const VkEventCreateInfo *pCreateInfo, 10432bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkEvent *pEvent) { 1043356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 104344a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateEvent(device, pCreateInfo, pAllocator, pEvent); 104355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (result == VK_SUCCESS) { 10436b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 104375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->eventMap[*pEvent].needsSignaled = false; 10438293ecfc5e69ed3978a8c04518166d828294870a4Tony Barbour dev_data->eventMap[*pEvent].write_in_use = 0; 104395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->eventMap[*pEvent].stageMask = VkPipelineStageFlags(0); 104405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 104415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 104425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 104435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 104449ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinskistatic bool PreCallValidateCreateSwapchainKHR(layer_data *dev_data, const char *func_name, 104459ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski VkSwapchainCreateInfoKHR const *pCreateInfo, SURFACE_STATE *surface_state, 104469ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski SWAPCHAIN_NODE *old_swapchain_state) { 10447d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes auto most_recent_swapchain = surface_state->swapchain ? surface_state->swapchain : surface_state->old_swapchain; 10448d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes 104494bd5f453535de3d3423ff1f9995b4acb15f791d2Chris Forbes // TODO: revisit this. some of these rules are being relaxed. 10450d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes if (most_recent_swapchain != old_swapchain_state || (surface_state->old_swapchain && surface_state->swapchain)) { 10451d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 10452d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes reinterpret_cast<uint64_t>(dev_data->device), __LINE__, DRAWSTATE_SWAPCHAIN_ALREADY_EXISTS, "DS", 104539ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s: surface has an existing swapchain other than oldSwapchain", func_name)) 10454d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes return true; 10455d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes } 10456d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes if (old_swapchain_state && old_swapchain_state->createInfo.surface != pCreateInfo->surface) { 10457d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 10458d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes reinterpret_cast<uint64_t const &>(pCreateInfo->oldSwapchain), __LINE__, DRAWSTATE_SWAPCHAIN_WRONG_SURFACE, 104599ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "DS", "%s: pCreateInfo->oldSwapchain's surface is not pCreateInfo->surface", func_name)) 10460d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes return true; 10461d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes } 104629a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto physical_device_state = GetPhysicalDeviceState(dev_data->instance_data, dev_data->physical_device); 104637de258f87ca1192db116a66b209253793d276ebcChris Forbes if (physical_device_state->vkGetPhysicalDeviceSurfaceCapabilitiesKHRState == UNCALLED) { 104647de258f87ca1192db116a66b209253793d276ebcChris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 104657de258f87ca1192db116a66b209253793d276ebcChris Forbes reinterpret_cast<uint64_t>(dev_data->physical_device), __LINE__, DRAWSTATE_SWAPCHAIN_CREATE_BEFORE_QUERY, "DS", 104669ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s: surface capabilities not retrieved for this physical device", func_name)) 104677de258f87ca1192db116a66b209253793d276ebcChris Forbes return true; 10468cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else { // have valid capabilities 104695c99b4daed164798f307244c9bde17b4f66014fbChris Forbes auto &capabilities = physical_device_state->surfaceCapabilities; 104709ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // Validate pCreateInfo->minImageCount against VkSurfaceCapabilitiesKHR::{min|max}ImageCount: 104712fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen if (pCreateInfo->minImageCount < capabilities.minImageCount) { 104722fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 104732fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t>(dev_data->device), __LINE__, VALIDATION_ERROR_02331, "DS", 104749ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s called with minImageCount = %d, which is outside the bounds returned " 104752fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen "by vkGetPhysicalDeviceSurfaceCapabilitiesKHR() (i.e. minImageCount = %d, maxImageCount = %d). %s", 104769ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski func_name, pCreateInfo->minImageCount, capabilities.minImageCount, capabilities.maxImageCount, 104772fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen validation_error_map[VALIDATION_ERROR_02331])) 104782fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen return true; 104792fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen } 104802fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen 104812fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen if ((capabilities.maxImageCount > 0) && (pCreateInfo->minImageCount > capabilities.maxImageCount)) { 104825c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 104832fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t>(dev_data->device), __LINE__, VALIDATION_ERROR_02332, "DS", 104849ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s called with minImageCount = %d, which is outside the bounds returned " 104852fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen "by vkGetPhysicalDeviceSurfaceCapabilitiesKHR() (i.e. minImageCount = %d, maxImageCount = %d). %s", 104869ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski func_name, pCreateInfo->minImageCount, capabilities.minImageCount, capabilities.maxImageCount, 104872fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen validation_error_map[VALIDATION_ERROR_02332])) 104885c99b4daed164798f307244c9bde17b4f66014fbChris Forbes return true; 104895c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 104902fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen 104919ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // Validate pCreateInfo->imageExtent against VkSurfaceCapabilitiesKHR::{current|min|max}ImageExtent: 104922e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill if ((capabilities.currentExtent.width == kSurfaceSizeFromSwapchain) && 104932e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill ((pCreateInfo->imageExtent.width < capabilities.minImageExtent.width) || 104942e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill (pCreateInfo->imageExtent.width > capabilities.maxImageExtent.width) || 104952e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill (pCreateInfo->imageExtent.height < capabilities.minImageExtent.height) || 104962e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill (pCreateInfo->imageExtent.height > capabilities.maxImageExtent.height))) { 104975c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 104982fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t>(dev_data->device), __LINE__, VALIDATION_ERROR_02334, "DS", 104999ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s called with imageExtent = (%d,%d), which is outside the bounds returned by " 105009ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "vkGetPhysicalDeviceSurfaceCapabilitiesKHR(): currentExtent = (%d,%d), minImageExtent = (%d,%d), " 105019ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "maxImageExtent = (%d,%d). %s", 105029ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski func_name, pCreateInfo->imageExtent.width, pCreateInfo->imageExtent.height, 105039ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski capabilities.currentExtent.width, capabilities.currentExtent.height, capabilities.minImageExtent.width, 105049ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski capabilities.minImageExtent.height, capabilities.maxImageExtent.width, capabilities.maxImageExtent.height, 105052fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen validation_error_map[VALIDATION_ERROR_02334])) 105065c99b4daed164798f307244c9bde17b4f66014fbChris Forbes return true; 105075c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 105082e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill if ((capabilities.currentExtent.width != kSurfaceSizeFromSwapchain) && 105092e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill ((pCreateInfo->imageExtent.width != capabilities.currentExtent.width) || 105102e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill (pCreateInfo->imageExtent.height != capabilities.currentExtent.height))) { 105115c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 105122fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t>(dev_data->device), __LINE__, VALIDATION_ERROR_02334, "DS", 105139ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s called with imageExtent = (%d,%d), which is not equal to the currentExtent = (%d,%d) returned by " 105149ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "vkGetPhysicalDeviceSurfaceCapabilitiesKHR(). %s", 105159ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski func_name, pCreateInfo->imageExtent.width, pCreateInfo->imageExtent.height, 105169ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski capabilities.currentExtent.width, capabilities.currentExtent.height, 105172fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen validation_error_map[VALIDATION_ERROR_02334])) 105185c99b4daed164798f307244c9bde17b4f66014fbChris Forbes return true; 105195c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 105209ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // pCreateInfo->preTransform should have exactly one bit set, and that bit must also be set in 105219ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // VkSurfaceCapabilitiesKHR::supportedTransforms. 105225c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (!pCreateInfo->preTransform || (pCreateInfo->preTransform & (pCreateInfo->preTransform - 1)) || 105235c99b4daed164798f307244c9bde17b4f66014fbChris Forbes !(pCreateInfo->preTransform & capabilities.supportedTransforms)) { 105249ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // This is an error situation; one for which we'd like to give the developer a helpful, multi-line error message. Build 105259ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // it up a little at a time, and then log it: 105265c99b4daed164798f307244c9bde17b4f66014fbChris Forbes std::string errorString = ""; 105275c99b4daed164798f307244c9bde17b4f66014fbChris Forbes char str[1024]; 105285c99b4daed164798f307244c9bde17b4f66014fbChris Forbes // Here's the first part of the message: 105299ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski sprintf(str, "%s called with a non-supported pCreateInfo->preTransform (i.e. %s). Supported values are:\n", func_name, 105305c99b4daed164798f307244c9bde17b4f66014fbChris Forbes string_VkSurfaceTransformFlagBitsKHR(pCreateInfo->preTransform)); 105315c99b4daed164798f307244c9bde17b4f66014fbChris Forbes errorString += str; 105325c99b4daed164798f307244c9bde17b4f66014fbChris Forbes for (int i = 0; i < 32; i++) { 105335c99b4daed164798f307244c9bde17b4f66014fbChris Forbes // Build up the rest of the message: 105345c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if ((1 << i) & capabilities.supportedTransforms) { 105355c99b4daed164798f307244c9bde17b4f66014fbChris Forbes const char *newStr = string_VkSurfaceTransformFlagBitsKHR((VkSurfaceTransformFlagBitsKHR)(1 << i)); 105365c99b4daed164798f307244c9bde17b4f66014fbChris Forbes sprintf(str, " %s\n", newStr); 105375c99b4daed164798f307244c9bde17b4f66014fbChris Forbes errorString += str; 105385c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 105395c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 105405c99b4daed164798f307244c9bde17b4f66014fbChris Forbes // Log the message that we've built up: 105415c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 105422fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t &>(dev_data->device), __LINE__, VALIDATION_ERROR_02339, "DS", "%s. %s", 105432fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen errorString.c_str(), validation_error_map[VALIDATION_ERROR_02339])) 105445c99b4daed164798f307244c9bde17b4f66014fbChris Forbes return true; 105455c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 105467b0d28d116977b91892f354e002edd760bdb86cbChris Forbes 105479ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // pCreateInfo->compositeAlpha should have exactly one bit set, and that bit must also be set in 105489ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // VkSurfaceCapabilitiesKHR::supportedCompositeAlpha 105495c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (!pCreateInfo->compositeAlpha || (pCreateInfo->compositeAlpha & (pCreateInfo->compositeAlpha - 1)) || 105505c99b4daed164798f307244c9bde17b4f66014fbChris Forbes !((pCreateInfo->compositeAlpha) & capabilities.supportedCompositeAlpha)) { 105519ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // This is an error situation; one for which we'd like to give the developer a helpful, multi-line error message. Build 105529ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // it up a little at a time, and then log it: 105535c99b4daed164798f307244c9bde17b4f66014fbChris Forbes std::string errorString = ""; 105545c99b4daed164798f307244c9bde17b4f66014fbChris Forbes char str[1024]; 105555c99b4daed164798f307244c9bde17b4f66014fbChris Forbes // Here's the first part of the message: 105569ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski sprintf(str, "%s called with a non-supported pCreateInfo->compositeAlpha (i.e. %s). Supported values are:\n", 105579ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski func_name, string_VkCompositeAlphaFlagBitsKHR(pCreateInfo->compositeAlpha)); 105585c99b4daed164798f307244c9bde17b4f66014fbChris Forbes errorString += str; 105595c99b4daed164798f307244c9bde17b4f66014fbChris Forbes for (int i = 0; i < 32; i++) { 105605c99b4daed164798f307244c9bde17b4f66014fbChris Forbes // Build up the rest of the message: 105615c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if ((1 << i) & capabilities.supportedCompositeAlpha) { 105625c99b4daed164798f307244c9bde17b4f66014fbChris Forbes const char *newStr = string_VkCompositeAlphaFlagBitsKHR((VkCompositeAlphaFlagBitsKHR)(1 << i)); 105635c99b4daed164798f307244c9bde17b4f66014fbChris Forbes sprintf(str, " %s\n", newStr); 105645c99b4daed164798f307244c9bde17b4f66014fbChris Forbes errorString += str; 105655c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 105665c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 105675c99b4daed164798f307244c9bde17b4f66014fbChris Forbes // Log the message that we've built up: 105685c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 105692fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t &>(dev_data->device), __LINE__, VALIDATION_ERROR_02340, "DS", "%s. %s", 105702fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen errorString.c_str(), validation_error_map[VALIDATION_ERROR_02340])) 105715c99b4daed164798f307244c9bde17b4f66014fbChris Forbes return true; 105725c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 105739ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // Validate pCreateInfo->imageArrayLayers against VkSurfaceCapabilitiesKHR::maxImageArrayLayers: 105745c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if ((pCreateInfo->imageArrayLayers < 1) || (pCreateInfo->imageArrayLayers > capabilities.maxImageArrayLayers)) { 105755c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 105762fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t>(dev_data->device), __LINE__, VALIDATION_ERROR_02335, "DS", 105779ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s called with a non-supported imageArrayLayers (i.e. %d). Minimum value is 1, maximum value is %d. %s", 105789ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski func_name, pCreateInfo->imageArrayLayers, capabilities.maxImageArrayLayers, 105792fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen validation_error_map[VALIDATION_ERROR_02335])) 105805c99b4daed164798f307244c9bde17b4f66014fbChris Forbes return true; 105815c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 105829ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // Validate pCreateInfo->imageUsage against VkSurfaceCapabilitiesKHR::supportedUsageFlags: 105835c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (pCreateInfo->imageUsage != (pCreateInfo->imageUsage & capabilities.supportedUsageFlags)) { 105845c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 105852fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t>(dev_data->device), __LINE__, VALIDATION_ERROR_02336, "DS", 105869ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s called with a non-supported pCreateInfo->imageUsage (i.e. 0x%08x). Supported flag bits are 0x%08x. %s", 105879ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski func_name, pCreateInfo->imageUsage, capabilities.supportedUsageFlags, 105889ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski validation_error_map[VALIDATION_ERROR_02336])) 105895c99b4daed164798f307244c9bde17b4f66014fbChris Forbes return true; 105905c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 105917de258f87ca1192db116a66b209253793d276ebcChris Forbes } 10592d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes 105939ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // Validate pCreateInfo values with the results of vkGetPhysicalDeviceSurfaceFormatsKHR(): 105945faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (physical_device_state->vkGetPhysicalDeviceSurfaceFormatsKHRState != QUERY_DETAILS) { 105955faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 105965faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes reinterpret_cast<uint64_t>(dev_data->device), __LINE__, DRAWSTATE_SWAPCHAIN_CREATE_BEFORE_QUERY, "DS", 105979ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s called before calling vkGetPhysicalDeviceSurfaceFormatsKHR().", func_name)) 105985faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes return true; 105995faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } else { 106009ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // Validate pCreateInfo->imageFormat against VkSurfaceFormatKHR::format: 106015faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes bool foundFormat = false; 106025faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes bool foundColorSpace = false; 106035faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes bool foundMatch = false; 106045faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes for (auto const &format : physical_device_state->surface_formats) { 106055faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (pCreateInfo->imageFormat == format.format) { 106069ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // Validate pCreateInfo->imageColorSpace against VkSurfaceFormatKHR::colorSpace: 106075faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes foundFormat = true; 106085faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (pCreateInfo->imageColorSpace == format.colorSpace) { 106095faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes foundMatch = true; 106105faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes break; 106115faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 106125faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } else { 106135faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (pCreateInfo->imageColorSpace == format.colorSpace) { 106145faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes foundColorSpace = true; 106155faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 106165faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 106175faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 106185faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (!foundMatch) { 106195faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (!foundFormat) { 106205faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 106212fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t>(dev_data->device), __LINE__, VALIDATION_ERROR_02333, "DS", 10622bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "%s called with a non-supported pCreateInfo->imageFormat (i.e. %d). %s", func_name, 10623bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pCreateInfo->imageFormat, validation_error_map[VALIDATION_ERROR_02333])) 106242fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen return true; 106252fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen } 106262fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen if (!foundColorSpace) { 106272fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 106282fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t>(dev_data->device), __LINE__, VALIDATION_ERROR_02333, "DS", 10629bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "%s called with a non-supported pCreateInfo->imageColorSpace (i.e. %d). %s", func_name, 10630bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pCreateInfo->imageColorSpace, validation_error_map[VALIDATION_ERROR_02333])) 106315faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes return true; 106325faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 106335faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 106345faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 106355faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes 106369ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // Validate pCreateInfo values with the results of vkGetPhysicalDeviceSurfacePresentModesKHR(): 106379e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (physical_device_state->vkGetPhysicalDeviceSurfacePresentModesKHRState != QUERY_DETAILS) { 1063825002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // FIFO is required to always be supported 106399e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (pCreateInfo->presentMode != VK_PRESENT_MODE_FIFO_KHR) { 106409e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 106419ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski reinterpret_cast<uint64_t>(dev_data->device), __LINE__, DRAWSTATE_SWAPCHAIN_CREATE_BEFORE_QUERY, "DS", 106429ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s called before calling vkGetPhysicalDeviceSurfacePresentModesKHR().", func_name)) 106439e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes return true; 106449e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 106459e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } else { 106469ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // Validate pCreateInfo->presentMode against vkGetPhysicalDeviceSurfacePresentModesKHR(): 10647bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski bool foundMatch = std::find(physical_device_state->present_modes.begin(), physical_device_state->present_modes.end(), 106489e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes pCreateInfo->presentMode) != physical_device_state->present_modes.end(); 106499e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (!foundMatch) { 106509e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 106512fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t>(dev_data->device), __LINE__, VALIDATION_ERROR_02341, "DS", 106529ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s called with a non-supported presentMode (i.e. %s). %s", func_name, 106532fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen string_VkPresentModeKHR(pCreateInfo->presentMode), validation_error_map[VALIDATION_ERROR_02341])) 106549e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes return true; 106559e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 106569e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 106579e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes 10658d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes return false; 10659d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes} 10660d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes 10661261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinskistatic void PostCallRecordCreateSwapchainKHR(layer_data *dev_data, VkResult result, const VkSwapchainCreateInfoKHR *pCreateInfo, 10662261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski VkSwapchainKHR *pSwapchain, SURFACE_STATE *surface_state, 10663261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski SWAPCHAIN_NODE *old_swapchain_state) { 106645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 10665b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 10666ddc5201048319558ce66701163a4546ee957af19Chris Forbes auto swapchain_state = unique_ptr<SWAPCHAIN_NODE>(new SWAPCHAIN_NODE(pCreateInfo, *pSwapchain)); 10667ddc5201048319558ce66701163a4546ee957af19Chris Forbes surface_state->swapchain = swapchain_state.get(); 10668ddc5201048319558ce66701163a4546ee957af19Chris Forbes dev_data->device_extensions.swapchainMap[*pSwapchain] = std::move(swapchain_state); 10669ddc5201048319558ce66701163a4546ee957af19Chris Forbes } else { 10670ddc5201048319558ce66701163a4546ee957af19Chris Forbes surface_state->swapchain = nullptr; 106715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 10672ddc5201048319558ce66701163a4546ee957af19Chris Forbes // Spec requires that even if CreateSwapchainKHR fails, oldSwapchain behaves as replaced. 106735b5488456e5afa0487f95b805a2aba59b13d69f4Chris Forbes if (old_swapchain_state) { 106745b5488456e5afa0487f95b805a2aba59b13d69f4Chris Forbes old_swapchain_state->replaced = true; 106755b5488456e5afa0487f95b805a2aba59b13d69f4Chris Forbes } 10676ddc5201048319558ce66701163a4546ee957af19Chris Forbes surface_state->old_swapchain = old_swapchain_state; 10677261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski return; 10678261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski} 10679261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski 10680261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo, 10681261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchain) { 1068256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 106839a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto surface_state = GetSurfaceState(dev_data->instance_data, pCreateInfo->surface); 106849a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto old_swapchain_state = GetSwapchainNode(dev_data, pCreateInfo->oldSwapchain); 10685261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski 106869ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski if (PreCallValidateCreateSwapchainKHR(dev_data, "vkCreateSwapChainKHR()", pCreateInfo, surface_state, old_swapchain_state)) { 10687261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski return VK_ERROR_VALIDATION_FAILED_EXT; 10688261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski } 10689261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski 10690261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski VkResult result = dev_data->dispatch_table.CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain); 10691261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski 10692261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski PostCallRecordCreateSwapchainKHR(dev_data, result, pCreateInfo, pSwapchain, surface_state, old_swapchain_state); 10693ddc5201048319558ce66701163a4546ee957af19Chris Forbes 106945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 106955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 106965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10697bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks *pAllocator) { 1069856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 1069983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 107005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10701b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 107029a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto swapchain_data = GetSwapchainNode(dev_data, swapchain); 10703b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis if (swapchain_data) { 10704b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis if (swapchain_data->images.size() > 0) { 10705b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis for (auto swapchain_image : swapchain_data->images) { 107065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto image_sub = dev_data->imageSubresourceMap.find(swapchain_image); 107075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (image_sub != dev_data->imageSubresourceMap.end()) { 107085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto imgsubpair : image_sub->second) { 107095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto image_item = dev_data->imageLayoutMap.find(imgsubpair); 107105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (image_item != dev_data->imageLayoutMap.end()) { 107115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->imageLayoutMap.erase(image_item); 107125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 107135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 107145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->imageSubresourceMap.erase(image_sub); 107155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 1071683b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call = 10717f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis ClearMemoryObjectBindings(dev_data, (uint64_t)swapchain_image, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT); 1071894c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis dev_data->imageMap.erase(swapchain_image); 107195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 107205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 10721ddc5201048319558ce66701163a4546ee957af19Chris Forbes 107229a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto surface_state = GetSurfaceState(dev_data->instance_data, swapchain_data->createInfo.surface); 10723ddc5201048319558ce66701163a4546ee957af19Chris Forbes if (surface_state) { 10724cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (surface_state->swapchain == swapchain_data) surface_state->swapchain = nullptr; 10725cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (surface_state->old_swapchain == swapchain_data) surface_state->old_swapchain = nullptr; 10726ddc5201048319558ce66701163a4546ee957af19Chris Forbes } 10727ddc5201048319558ce66701163a4546ee957af19Chris Forbes 107285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->device_extensions.swapchainMap.erase(swapchain); 107295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 10730b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 10731cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip_call) dev_data->dispatch_table.DestroySwapchainKHR(device, swapchain, pAllocator); 107325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 107335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10734bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL GetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t *pCount, 10735bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkImage *pSwapchainImages) { 1073656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 107374a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.GetSwapchainImagesKHR(device, swapchain, pCount, pSwapchainImages); 107385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 107395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (result == VK_SUCCESS && pSwapchainImages != NULL) { 107405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // This should never happen and is checked by param checker. 10741cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!pCount) return result; 10742b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 107435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const size_t count = *pCount; 107449a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto swapchain_node = GetSwapchainNode(dev_data, swapchain); 10745b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis if (swapchain_node && !swapchain_node->images.empty()) { 107460801763633180d277d26a90343464bd11646056fTobin Ehlis // TODO : Not sure I like the memcmp here, but it works 107470801763633180d277d26a90343464bd11646056fTobin Ehlis const bool mismatch = (swapchain_node->images.size() != count || 107480801763633180d277d26a90343464bd11646056fTobin Ehlis memcmp(&swapchain_node->images[0], pSwapchainImages, sizeof(swapchain_node->images[0]) * count)); 107495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (mismatch) { 107505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODO: Verify against Valid Usage section of extension 107515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 107525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (uint64_t)swapchain, __LINE__, MEMTRACK_NONE, "SWAP_CHAIN", 10753414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller "vkGetSwapchainInfoKHR(0x%" PRIx64 107545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis ", VK_SWAP_CHAIN_INFO_TYPE_PERSISTENT_IMAGES_KHR) returned mismatching data", 107555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (uint64_t)(swapchain)); 107565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 107575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 107585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < *pCount; ++i) { 107595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis IMAGE_LAYOUT_NODE image_layout_node; 107605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis image_layout_node.layout = VK_IMAGE_LAYOUT_UNDEFINED; 107615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis image_layout_node.format = swapchain_node->createInfo.imageFormat; 107626d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis // Add imageMap entries for each swapchain image 107636d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis VkImageCreateInfo image_ci = {}; 10764eb6ea7587bdc06e98a89398f113fe3610d270dcbChris Forbes image_ci.flags = 0; 10765eb6ea7587bdc06e98a89398f113fe3610d270dcbChris Forbes image_ci.imageType = VK_IMAGE_TYPE_2D; 107666d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis image_ci.format = swapchain_node->createInfo.imageFormat; 107676d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis image_ci.extent.width = swapchain_node->createInfo.imageExtent.width; 107686d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis image_ci.extent.height = swapchain_node->createInfo.imageExtent.height; 10769d1a9776c1a22ec99a3ef0dd44e7f85a78a04d1edTony Barbour image_ci.extent.depth = 1; 10770eb6ea7587bdc06e98a89398f113fe3610d270dcbChris Forbes image_ci.mipLevels = 1; 10771eb6ea7587bdc06e98a89398f113fe3610d270dcbChris Forbes image_ci.arrayLayers = swapchain_node->createInfo.imageArrayLayers; 10772eb6ea7587bdc06e98a89398f113fe3610d270dcbChris Forbes image_ci.samples = VK_SAMPLE_COUNT_1_BIT; 10773eb6ea7587bdc06e98a89398f113fe3610d270dcbChris Forbes image_ci.tiling = VK_IMAGE_TILING_OPTIMAL; 10774eb6ea7587bdc06e98a89398f113fe3610d270dcbChris Forbes image_ci.usage = swapchain_node->createInfo.imageUsage; 107756d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis image_ci.sharingMode = swapchain_node->createInfo.imageSharingMode; 107761facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis dev_data->imageMap[pSwapchainImages[i]] = unique_ptr<IMAGE_STATE>(new IMAGE_STATE(pSwapchainImages[i], &image_ci)); 107771facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis auto &image_state = dev_data->imageMap[pSwapchainImages[i]]; 107781facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis image_state->valid = false; 10779e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis image_state->binding.mem = MEMTRACKER_SWAP_CHAIN_IMAGE_KEY; 107805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis swapchain_node->images.push_back(pSwapchainImages[i]); 107815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis ImageSubresourcePair subpair = {pSwapchainImages[i], false, VkImageSubresource()}; 107825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->imageSubresourceMap[pSwapchainImages[i]].push_back(subpair); 107835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->imageLayoutMap[subpair] = image_layout_node; 107845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->device_extensions.imageToSwapchainMap[pSwapchainImages[i]] = swapchain; 107855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 107865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 107875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 107885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 107895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1079089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo) { 1079156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map); 107925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool skip_call = false; 107935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 107946c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes std::lock_guard<std::mutex> lock(global_lock); 107959a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto queue_state = GetQueueState(dev_data, queue); 107961671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes 107976c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes for (uint32_t i = 0; i < pPresentInfo->waitSemaphoreCount; ++i) { 107989a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pSemaphore = GetSemaphoreNode(dev_data, pPresentInfo->pWaitSemaphores[i]); 107996c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes if (pSemaphore && !pSemaphore->signaled) { 10800226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 10801226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, 10802226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "DS", "Queue 0x%p is waiting on semaphore 0x%" PRIx64 " that has no way to be signaled.", queue, 10803226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis reinterpret_cast<const uint64_t &>(pPresentInfo->pWaitSemaphores[i])); 108045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 108056c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes } 10806249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis 108076c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes for (uint32_t i = 0; i < pPresentInfo->swapchainCount; ++i) { 108089a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto swapchain_data = GetSwapchainNode(dev_data, pPresentInfo->pSwapchains[i]); 10809a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes if (swapchain_data) { 10810a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes if (pPresentInfo->pImageIndices[i] >= swapchain_data->images.size()) { 10811bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski skip_call |= log_msg( 10812bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 10813bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski reinterpret_cast<uint64_t const &>(pPresentInfo->pSwapchains[i]), __LINE__, DRAWSTATE_SWAPCHAIN_INVALID_IMAGE, 10814bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "DS", "vkQueuePresentKHR: Swapchain image index too large (%u). There are only %u images in this swapchain.", 10815bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pPresentInfo->pImageIndices[i], (uint32_t)swapchain_data->images.size()); 10816bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski } else { 10817a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes auto image = swapchain_data->images[pPresentInfo->pImageIndices[i]]; 108189a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_state = GetImageState(dev_data, image); 108191facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis skip_call |= ValidateImageMemoryIsValid(dev_data, image_state, "vkQueuePresentKHR()"); 10820a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes 108211facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis if (!image_state->acquired) { 10822bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski skip_call |= log_msg( 10823bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 10824bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski reinterpret_cast<uint64_t const &>(pPresentInfo->pSwapchains[i]), __LINE__, 10825bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski DRAWSTATE_SWAPCHAIN_IMAGE_NOT_ACQUIRED, "DS", 10826bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "vkQueuePresentKHR: Swapchain image index %u has not been acquired.", pPresentInfo->pImageIndices[i]); 10827a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes } 10828a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes 10829a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes vector<VkImageLayout> layouts; 10830a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes if (FindLayouts(dev_data, image, layouts)) { 10831a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes for (auto layout : layouts) { 10832a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes if (layout != VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) { 10833a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes skip_call |= 108342fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT, 108352fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t &>(queue), __LINE__, VALIDATION_ERROR_01964, "DS", 108362fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen "Images passed to present must be in layout " 108372fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen "VK_IMAGE_LAYOUT_PRESENT_SRC_KHR but is in %s. %s", 108382fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen string_VkImageLayout(layout), validation_error_map[VALIDATION_ERROR_01964]); 10839a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes } 108405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 108415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 108425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 108431671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes 108441671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes // All physical devices and queue families are required to be able 108451671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes // to present to any native window on Android; require the 108461671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes // application to have established support on any other platform. 108471671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes if (!dev_data->instance_data->androidSurfaceExtensionEnabled) { 108489a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto surface_state = GetSurfaceState(dev_data->instance_data, swapchain_data->createInfo.surface); 108491671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes auto support_it = surface_state->gpu_queue_support.find({dev_data->physical_device, queue_state->queueFamilyIndex}); 108501671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes 108511671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes if (support_it == surface_state->gpu_queue_support.end()) { 108521671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes skip_call |= 108531671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 108541671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes reinterpret_cast<uint64_t const &>(pPresentInfo->pSwapchains[i]), __LINE__, 10855cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski DRAWSTATE_SWAPCHAIN_UNSUPPORTED_QUEUE, "DS", 10856cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkQueuePresentKHR: Presenting image without calling " 10857cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkGetPhysicalDeviceSurfaceSupportKHR"); 108581671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes } else if (!support_it->second) { 10859cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski skip_call |= log_msg( 10860cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 10861cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski reinterpret_cast<uint64_t const &>(pPresentInfo->pSwapchains[i]), __LINE__, VALIDATION_ERROR_01961, "DS", 10862cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkQueuePresentKHR: Presenting image on queue that cannot " 10863cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "present to this surface. %s", 10864cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski validation_error_map[VALIDATION_ERROR_01961]); 108651671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes } 108661671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes } 108675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 108685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 108695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 108706c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes if (skip_call) { 108716c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes return VK_ERROR_VALIDATION_FAILED_EXT; 108726c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes } 108736c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes 108744a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.QueuePresentKHR(queue, pPresentInfo); 108756c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes 108766c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes if (result != VK_ERROR_VALIDATION_FAILED_EXT) { 108776c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes // Semaphore waits occur before error generation, if the call reached 108786c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes // the ICD. (Confirm?) 108796c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes for (uint32_t i = 0; i < pPresentInfo->waitSemaphoreCount; ++i) { 108809a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pSemaphore = GetSemaphoreNode(dev_data, pPresentInfo->pWaitSemaphores[i]); 108819867daedbf52debc77d6568162ee21e071699b80Chris Forbes if (pSemaphore) { 108829867daedbf52debc77d6568162ee21e071699b80Chris Forbes pSemaphore->signaler.first = VK_NULL_HANDLE; 108836c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes pSemaphore->signaled = false; 108846c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes } 108856c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes } 108869867daedbf52debc77d6568162ee21e071699b80Chris Forbes 10887220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes for (uint32_t i = 0; i < pPresentInfo->swapchainCount; ++i) { 10888220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes // Note: this is imperfect, in that we can get confused about what 10889220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes // did or didn't succeed-- but if the app does that, it's confused 10890220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes // itself just as much. 10891220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes auto local_result = pPresentInfo->pResults ? pPresentInfo->pResults[i] : result; 10892220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes 10893cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (local_result != VK_SUCCESS && local_result != VK_SUBOPTIMAL_KHR) continue; // this present didn't actually happen. 10894220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes 10895220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes // Mark the image as having been released to the WSI 108969a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto swapchain_data = GetSwapchainNode(dev_data, pPresentInfo->pSwapchains[i]); 10897220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes auto image = swapchain_data->images[pPresentInfo->pImageIndices[i]]; 108989a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_state = GetImageState(dev_data, image); 108991facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis image_state->acquired = false; 10900220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes } 10901220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes 109029867daedbf52debc77d6568162ee21e071699b80Chris Forbes // Note: even though presentation is directed to a queue, there is no 109039867daedbf52debc77d6568162ee21e071699b80Chris Forbes // direct ordering between QP and subsequent work, so QP (and its 109049867daedbf52debc77d6568162ee21e071699b80Chris Forbes // semaphore waits) /never/ participate in any completion proof. 109056c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes } 109061344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis 109075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 109085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 109095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10910c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinskistatic bool PreCallValidateCreateSharedSwapchainsKHR(layer_data *dev_data, uint32_t swapchainCount, 10911c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski const VkSwapchainCreateInfoKHR *pCreateInfos, VkSwapchainKHR *pSwapchains, 10912c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski std::vector<SURFACE_STATE *> &surface_state, 10913c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski std::vector<SWAPCHAIN_NODE *> &old_swapchain_state) { 109140342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski if (pCreateInfos) { 10915c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski std::lock_guard<std::mutex> lock(global_lock); 109160342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski for (uint32_t i = 0; i < swapchainCount; i++) { 109179a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis surface_state.push_back(GetSurfaceState(dev_data->instance_data, pCreateInfos[i].surface)); 109189a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis old_swapchain_state.push_back(GetSwapchainNode(dev_data, pCreateInfos[i].oldSwapchain)); 109199ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski std::stringstream func_name; 109209ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski func_name << "vkCreateSharedSwapchainsKHR[" << swapchainCount << "]"; 10921bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (PreCallValidateCreateSwapchainKHR(dev_data, func_name.str().c_str(), &pCreateInfos[i], surface_state[i], 10922bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski old_swapchain_state[i])) { 10923c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski return true; 109240342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski } 109250342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski } 109260342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski } 10927c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski return false; 10928c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski} 109290342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski 10930c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinskistatic void PostCallRecordCreateSharedSwapchainsKHR(layer_data *dev_data, VkResult result, uint32_t swapchainCount, 10931c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski const VkSwapchainCreateInfoKHR *pCreateInfos, VkSwapchainKHR *pSwapchains, 10932c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski std::vector<SURFACE_STATE *> &surface_state, 10933c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski std::vector<SWAPCHAIN_NODE *> &old_swapchain_state) { 109340342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski if (VK_SUCCESS == result) { 109350342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski for (uint32_t i = 0; i < swapchainCount; i++) { 109360342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski auto swapchain_state = unique_ptr<SWAPCHAIN_NODE>(new SWAPCHAIN_NODE(&pCreateInfos[i], pSwapchains[i])); 109370342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski surface_state[i]->swapchain = swapchain_state.get(); 109380342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski dev_data->device_extensions.swapchainMap[pSwapchains[i]] = std::move(swapchain_state); 109390342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski } 109400342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski } else { 109410342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski for (uint32_t i = 0; i < swapchainCount; i++) { 109420342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski surface_state[i]->swapchain = nullptr; 109430342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski } 109440342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski } 109450342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski // Spec requires that even if CreateSharedSwapchainKHR fails, oldSwapchain behaves as replaced. 109460342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski for (uint32_t i = 0; i < swapchainCount; i++) { 109470342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski if (old_swapchain_state[i]) { 109480342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski old_swapchain_state[i]->replaced = true; 109490342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski } 109500342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski surface_state[i]->old_swapchain = old_swapchain_state[i]; 109510342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski } 10952c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski return; 10953c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski} 10954c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski 10955c6cd632d064579a64e61d8704b411d0e4ace7adaMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateSharedSwapchainsKHR(VkDevice device, uint32_t swapchainCount, 10956c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski const VkSwapchainCreateInfoKHR *pCreateInfos, 10957c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchains) { 1095856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 10959c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski std::vector<SURFACE_STATE *> surface_state; 10960c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski std::vector<SWAPCHAIN_NODE *> old_swapchain_state; 10961c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski 10962c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski if (PreCallValidateCreateSharedSwapchainsKHR(dev_data, swapchainCount, pCreateInfos, pSwapchains, surface_state, 10963c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski old_swapchain_state)) { 10964c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski return VK_ERROR_VALIDATION_FAILED_EXT; 10965c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski } 10966c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski 10967c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski VkResult result = 10968c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski dev_data->dispatch_table.CreateSharedSwapchainsKHR(device, swapchainCount, pCreateInfos, pAllocator, pSwapchains); 10969c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski 10970c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski PostCallRecordCreateSharedSwapchainsKHR(dev_data, result, swapchainCount, pCreateInfos, pSwapchains, surface_state, 10971c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski old_swapchain_state); 109720342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski 10973c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young return result; 10974c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young} 10975c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young 1097689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL AcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, 1097789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu VkSemaphore semaphore, VkFence fence, uint32_t *pImageIndex) { 1097856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 1097983b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 109801344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis 10981b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 10982449670637ef4214b33018f497cf10daeff9dc85bChris Forbes 10983449670637ef4214b33018f497cf10daeff9dc85bChris Forbes if (fence == VK_NULL_HANDLE && semaphore == VK_NULL_HANDLE) { 10984449670637ef4214b33018f497cf10daeff9dc85bChris Forbes skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 10985d17d86d15a733f1ec988956721ea4b7cdfb6771bChris Forbes reinterpret_cast<uint64_t &>(device), __LINE__, DRAWSTATE_SWAPCHAIN_NO_SYNC_FOR_ACQUIRE, "DS", 10986449670637ef4214b33018f497cf10daeff9dc85bChris Forbes "vkAcquireNextImageKHR: Semaphore and fence cannot both be VK_NULL_HANDLE. There would be no way " 10987449670637ef4214b33018f497cf10daeff9dc85bChris Forbes "to determine the completion of this operation."); 10988449670637ef4214b33018f497cf10daeff9dc85bChris Forbes } 10989449670637ef4214b33018f497cf10daeff9dc85bChris Forbes 109909a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pSemaphore = GetSemaphoreNode(dev_data, semaphore); 10991f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes if (pSemaphore && pSemaphore->signaled) { 1099283b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT, 109932fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<const uint64_t &>(semaphore), __LINE__, VALIDATION_ERROR_01952, "DS", 109942fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen "vkAcquireNextImageKHR: Semaphore must not be currently signaled or in a wait state. %s", 109952fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen validation_error_map[VALIDATION_ERROR_01952]); 109965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 10997f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes 109989a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pFence = GetFenceNode(dev_data, fence); 10999f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes if (pFence) { 1100083b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis skip_call |= ValidateFenceForSubmit(dev_data, pFence); 110015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 110024a5614452104c88cb04390dac882dd94ebdcc3deChris Forbes 110039a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto swapchain_data = GetSwapchainNode(dev_data, swapchain); 11004fc9f0448c3cb6ba4fc018fefe761bb43a1884846Chris Forbes 11005fc9f0448c3cb6ba4fc018fefe761bb43a1884846Chris Forbes if (swapchain_data->replaced) { 11006fc9f0448c3cb6ba4fc018fefe761bb43a1884846Chris Forbes skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 11007fc9f0448c3cb6ba4fc018fefe761bb43a1884846Chris Forbes reinterpret_cast<uint64_t &>(swapchain), __LINE__, DRAWSTATE_SWAPCHAIN_REPLACED, "DS", 11008fc9f0448c3cb6ba4fc018fefe761bb43a1884846Chris Forbes "vkAcquireNextImageKHR: This swapchain has been replaced. The application can still " 11009fc9f0448c3cb6ba4fc018fefe761bb43a1884846Chris Forbes "present any images it has acquired, but cannot acquire any more."); 11010fc9f0448c3cb6ba4fc018fefe761bb43a1884846Chris Forbes } 11011fc9f0448c3cb6ba4fc018fefe761bb43a1884846Chris Forbes 110129a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto physical_device_state = GetPhysicalDeviceState(dev_data->instance_data, dev_data->physical_device); 110134a5614452104c88cb04390dac882dd94ebdcc3deChris Forbes if (physical_device_state->vkGetPhysicalDeviceSurfaceCapabilitiesKHRState != UNCALLED) { 110146569ab421f45f905e69fa7345bda4fe5b87e9045Mark Lobodzinski uint64_t acquired_images = std::count_if(swapchain_data->images.begin(), swapchain_data->images.end(), 110159a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis [=](VkImage image) { return GetImageState(dev_data, image)->acquired; }); 110164a5614452104c88cb04390dac882dd94ebdcc3deChris Forbes if (acquired_images > swapchain_data->images.size() - physical_device_state->surfaceCapabilities.minImageCount) { 110176569ab421f45f905e69fa7345bda4fe5b87e9045Mark Lobodzinski skip_call |= 110186569ab421f45f905e69fa7345bda4fe5b87e9045Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 110196569ab421f45f905e69fa7345bda4fe5b87e9045Mark Lobodzinski reinterpret_cast<uint64_t const &>(swapchain), __LINE__, DRAWSTATE_SWAPCHAIN_TOO_MANY_IMAGES, "DS", 110206569ab421f45f905e69fa7345bda4fe5b87e9045Mark Lobodzinski "vkAcquireNextImageKHR: Application has already acquired the maximum number of images (0x%" PRIxLEAST64 ")", 110216569ab421f45f905e69fa7345bda4fe5b87e9045Mark Lobodzinski acquired_images); 110224a5614452104c88cb04390dac882dd94ebdcc3deChris Forbes } 110234a5614452104c88cb04390dac882dd94ebdcc3deChris Forbes } 1102475269fc9e5cc9696ddf3dd28ff201c9b2526dc7aThomas Louis 1102575269fc9e5cc9696ddf3dd28ff201c9b2526dc7aThomas Louis if (swapchain_data->images.size() == 0) { 1102675269fc9e5cc9696ddf3dd28ff201c9b2526dc7aThomas Louis skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 1102775269fc9e5cc9696ddf3dd28ff201c9b2526dc7aThomas Louis reinterpret_cast<uint64_t const &>(swapchain), __LINE__, DRAWSTATE_SWAPCHAIN_IMAGES_NOT_FOUND, "DS", 1102875269fc9e5cc9696ddf3dd28ff201c9b2526dc7aThomas Louis "vkAcquireNextImageKHR: No images found to acquire from. Application probably did not call " 1102975269fc9e5cc9696ddf3dd28ff201c9b2526dc7aThomas Louis "vkGetSwapchainImagesKHR after swapchain creation."); 1103075269fc9e5cc9696ddf3dd28ff201c9b2526dc7aThomas Louis } 1103175269fc9e5cc9696ddf3dd28ff201c9b2526dc7aThomas Louis 11032b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 110331344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis 11034cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip_call) return VK_ERROR_VALIDATION_FAILED_EXT; 11035f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes 110364a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.AcquireNextImageKHR(device, swapchain, timeout, semaphore, fence, pImageIndex); 11037f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes 11038f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes lock.lock(); 11039f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes if (result == VK_SUCCESS || result == VK_SUBOPTIMAL_KHR) { 11040f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes if (pFence) { 11041f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes pFence->state = FENCE_INFLIGHT; 11042cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pFence->signaler.first = VK_NULL_HANDLE; // ANI isn't on a queue, so this can't participate in a completion proof. 11043f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes } 11044f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes 11045f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes // A successful call to AcquireNextImageKHR counts as a signal operation on semaphore 11046f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes if (pSemaphore) { 11047f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes pSemaphore->signaled = true; 110489867daedbf52debc77d6568162ee21e071699b80Chris Forbes pSemaphore->signaler.first = VK_NULL_HANDLE; 11049f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes } 11050220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes 11051220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes // Mark the image as acquired. 11052220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes auto image = swapchain_data->images[*pImageIndex]; 110539a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_state = GetImageState(dev_data, image); 110541facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis image_state->acquired = true; 110555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 11056f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes lock.unlock(); 110571344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis 110585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 110595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 110605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 11061f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL EnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount, 11062f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski VkPhysicalDevice *pPhysicalDevices) { 1106383b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis bool skip_call = false; 1106456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 11065bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis assert(instance_data); 11066219f00ffed576643641976122fa1db8e5fce5dc1Chris Forbes 11067bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis // For this instance, flag when vkEnumeratePhysicalDevices goes to QUERY_COUNT and then QUERY_DETAILS 11068bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis if (NULL == pPhysicalDevices) { 11069bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis instance_data->vkEnumeratePhysicalDevicesState = QUERY_COUNT; 11070f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski } else { 11071bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis if (UNCALLED == instance_data->vkEnumeratePhysicalDevicesState) { 11072bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis // Flag warning here. You can call this without having queried the count, but it may not be 11073bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis // robust on platforms with multiple physical devices. 11074bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis skip_call |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, 11075bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, 0, __LINE__, DEVLIMITS_MISSING_QUERY_COUNT, "DL", 11076bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis "Call sequence has vkEnumeratePhysicalDevices() w/ non-NULL pPhysicalDevices. You should first " 11077bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis "call vkEnumeratePhysicalDevices() w/ NULL pPhysicalDevices to query pPhysicalDeviceCount."); 11078cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } // TODO : Could also flag a warning if re-calling this function in QUERY_DETAILS state 11079bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis else if (instance_data->physical_devices_count != *pPhysicalDeviceCount) { 11080bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis // Having actual count match count from app is not a requirement, so this can be a warning 11081bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis skip_call |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, 11082bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_COUNT_MISMATCH, "DL", 11083bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis "Call to vkEnumeratePhysicalDevices() w/ pPhysicalDeviceCount value %u, but actual count " 11084bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis "supported by this instance is %u.", 11085bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis *pPhysicalDeviceCount, instance_data->physical_devices_count); 11086bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis } 11087bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis instance_data->vkEnumeratePhysicalDevicesState = QUERY_DETAILS; 11088f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski } 11089bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis if (skip_call) { 11090bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis return VK_ERROR_VALIDATION_FAILED_EXT; 11091bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis } 11092bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis VkResult result = instance_data->dispatch_table.EnumeratePhysicalDevices(instance, pPhysicalDeviceCount, pPhysicalDevices); 11093bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis if (NULL == pPhysicalDevices) { 11094bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis instance_data->physical_devices_count = *pPhysicalDeviceCount; 11095cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else if (result == VK_SUCCESS) { // Save physical devices 11096bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++) { 11097bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis auto &phys_device_state = instance_data->physical_device_map[pPhysicalDevices[i]]; 11098bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis phys_device_state.phys_device = pPhysicalDevices[i]; 11099bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis // Init actual features for each physical device 11100bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis instance_data->dispatch_table.GetPhysicalDeviceFeatures(pPhysicalDevices[i], &phys_device_state.features); 11101bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis } 11102bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis } 11103bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis return result; 11104f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski} 11105f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski 1110643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis// Common function to handle validation for GetPhysicalDeviceQueueFamilyProperties & 2KHR version 1110743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic bool ValidateCommonGetPhysicalDeviceQueueFamilyProperties(instance_layer_data *instance_data, 1110843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis PHYSICAL_DEVICE_STATE *pd_state, 1110943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis uint32_t *pQueueFamilyPropertyCount, bool qfp_null, 1111043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis const char *count_var_name, const char *caller_name) { 1111143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis bool skip = false; 1111243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis if (qfp_null) { 1111343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis pd_state->vkGetPhysicalDeviceQueueFamilyPropertiesState = QUERY_COUNT; 1111443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } else { 1111543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis // Verify that for each physical device, this function is called first with NULL pQueueFamilyProperties ptr in order to get 1111643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis // count 1111743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis if (UNCALLED == pd_state->vkGetPhysicalDeviceQueueFamilyPropertiesState) { 1111843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, 1111943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_MISSING_QUERY_COUNT, "DL", 1112043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis "Call sequence has %s() w/ non-NULL " 1112143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis "pQueueFamilyProperties. You should first call %s() w/ " 1112243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis "NULL pQueueFamilyProperties to query pCount.", 1112343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis caller_name, caller_name); 1112443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 1112543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis // Then verify that pCount that is passed in on second call matches what was returned 1112643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis if (pd_state->queueFamilyPropertiesCount != *pQueueFamilyPropertyCount) { 1112743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis // TODO: this is not a requirement of the Valid Usage section for vkGetPhysicalDeviceQueueFamilyProperties, so 1112843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis // provide as warning 1112943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, 1113043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_COUNT_MISMATCH, "DL", 1113143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis "Call to %s() w/ %s value %u, but actual count supported by this physicalDevice is %u.", caller_name, 1113243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis count_var_name, *pQueueFamilyPropertyCount, pd_state->queueFamilyPropertiesCount); 1113343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 1113443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis pd_state->vkGetPhysicalDeviceQueueFamilyPropertiesState = QUERY_DETAILS; 1113543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 1113643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis return skip; 1113743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis} 1113843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis 1113943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic bool PreCallValidateGetPhysicalDeviceQueueFamilyProperties(instance_layer_data *instance_data, 1114043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis PHYSICAL_DEVICE_STATE *pd_state, uint32_t *pCount, 1114143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis VkQueueFamilyProperties *pQueueFamilyProperties) { 1114243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis return ValidateCommonGetPhysicalDeviceQueueFamilyProperties(instance_data, pd_state, pCount, 1114343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis (nullptr == pQueueFamilyProperties), "pCount", 1114443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis "vkGetPhysicalDeviceQueueFamilyProperties()"); 1114543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis} 1114643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis 1114743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic bool PreCallValidateGetPhysicalDeviceQueueFamilyProperties2KHR(instance_layer_data *instance_data, 1114843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis PHYSICAL_DEVICE_STATE *pd_state, 1114943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis uint32_t *pQueueFamilyPropertyCount, 1115043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis VkQueueFamilyProperties2KHR *pQueueFamilyProperties) { 1115143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis return ValidateCommonGetPhysicalDeviceQueueFamilyProperties(instance_data, pd_state, pQueueFamilyPropertyCount, 1115243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis (nullptr == pQueueFamilyProperties), "pQueueFamilyPropertyCount", 1115343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis "vkGetPhysicalDeviceQueueFamilyProperties2KHR()"); 1115443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis} 1115543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis 1115643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis// Common function to update state for GetPhysicalDeviceQueueFamilyProperties & 2KHR version 1115743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic void StateUpdateCommonGetPhysicalDeviceQueueFamilyProperties(PHYSICAL_DEVICE_STATE *pd_state, uint32_t count, 1115843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis VkQueueFamilyProperties2KHR *pQueueFamilyProperties) { 1115943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis if (!pQueueFamilyProperties) { 1116043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis pd_state->queueFamilyPropertiesCount = count; 1116143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } else { // Save queue family properties 1116243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis if (pd_state->queue_family_properties.size() < count) pd_state->queue_family_properties.resize(count); 1116343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis for (uint32_t i = 0; i < count; i++) { 1116443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis pd_state->queue_family_properties[i] = pQueueFamilyProperties[i].queueFamilyProperties; 1116543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 1116643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 1116743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis} 1116843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis 1116943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic void PostCallRecordGetPhysicalDeviceQueueFamilyProperties(PHYSICAL_DEVICE_STATE *pd_state, uint32_t count, 1117043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis VkQueueFamilyProperties *pQueueFamilyProperties) { 1117143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis VkQueueFamilyProperties2KHR *pqfp = nullptr; 1117243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis std::vector<VkQueueFamilyProperties2KHR> qfp; 1117343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis qfp.resize(count); 1117443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis if (pQueueFamilyProperties) { 1117543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis for (uint32_t i = 0; i < count; ++i) { 1117643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis qfp[i].sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2_KHR; 1117743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis qfp[i].pNext = nullptr; 1117843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis qfp[i].queueFamilyProperties = pQueueFamilyProperties[i]; 1117943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 1118043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis pqfp = qfp.data(); 1118143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 1118243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis StateUpdateCommonGetPhysicalDeviceQueueFamilyProperties(pd_state, count, pqfp); 1118343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis} 1118443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis 1118543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic void PostCallRecordGetPhysicalDeviceQueueFamilyProperties2KHR(PHYSICAL_DEVICE_STATE *pd_state, uint32_t count, 1118643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis VkQueueFamilyProperties2KHR *pQueueFamilyProperties) { 1118743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis StateUpdateCommonGetPhysicalDeviceQueueFamilyProperties(pd_state, count, pQueueFamilyProperties); 1118843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis} 1118943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis 11190bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, 11191bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkQueueFamilyProperties *pQueueFamilyProperties) { 1119256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 111939a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto physical_device_state = GetPhysicalDeviceState(instance_data, physicalDevice); 1119443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis assert(physical_device_state); 1119543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis bool skip = 1119643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis PreCallValidateGetPhysicalDeviceQueueFamilyProperties(instance_data, physical_device_state, pCount, pQueueFamilyProperties); 1119743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis if (skip) { 1119843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis return; 1119943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 1120043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis instance_data->dispatch_table.GetPhysicalDeviceQueueFamilyProperties(physicalDevice, pCount, pQueueFamilyProperties); 1120143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis PostCallRecordGetPhysicalDeviceQueueFamilyProperties(physical_device_state, *pCount, pQueueFamilyProperties); 1120243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis} 1120343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis 1120443947a6175e3e942e04d902f4d18928168e2d0dbTobin EhlisVKAPI_ATTR void VKAPI_CALL GetPhysicalDeviceQueueFamilyProperties2KHR(VkPhysicalDevice physicalDevice, 1120543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis uint32_t *pQueueFamilyPropertyCount, 1120643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis VkQueueFamilyProperties2KHR *pQueueFamilyProperties) { 1120756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 112089a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto physical_device_state = GetPhysicalDeviceState(instance_data, physicalDevice); 1120943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis assert(physical_device_state); 1121043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis bool skip = PreCallValidateGetPhysicalDeviceQueueFamilyProperties2KHR(instance_data, physical_device_state, 1121143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis pQueueFamilyPropertyCount, pQueueFamilyProperties); 1121243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis if (skip) { 1121343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis return; 11214cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski } 1121543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis instance_data->dispatch_table.GetPhysicalDeviceQueueFamilyProperties2KHR(physicalDevice, pQueueFamilyPropertyCount, 1121643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis pQueueFamilyProperties); 1121743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis PostCallRecordGetPhysicalDeviceQueueFamilyProperties2KHR(physical_device_state, *pQueueFamilyPropertyCount, 1121843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis pQueueFamilyProperties); 11219cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski} 11220cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski 11221bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskitemplate <typename TCreateInfo, typename FPtr> 11222bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic VkResult CreateSurface(VkInstance instance, TCreateInfo const *pCreateInfo, VkAllocationCallbacks const *pAllocator, 11223bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkSurfaceKHR *pSurface, FPtr fptr) { 1122456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 11225747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11226747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes // Call down the call chain: 11227747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes VkResult result = (instance_data->dispatch_table.*fptr)(instance, pCreateInfo, pAllocator, pSurface); 11228747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11229747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (result == VK_SUCCESS) { 11230747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes std::unique_lock<std::mutex> lock(global_lock); 11231747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->surface_map[*pSurface] = SURFACE_STATE(*pSurface); 11232747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes lock.unlock(); 11233747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes } 11234747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11235747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes return result; 11236747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 11237747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11238747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR void VKAPI_CALL DestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks *pAllocator) { 11239747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes bool skip_call = false; 1124056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 11241747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes std::unique_lock<std::mutex> lock(global_lock); 112429a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto surface_state = GetSurfaceState(instance_data, surface); 11243747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11244747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (surface_state) { 11245747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes // TODO: track swapchains created from this surface. 11246747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->surface_map.erase(surface); 11247747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes } 11248747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes lock.unlock(); 11249747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11250747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (!skip_call) { 11251747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes // Call down the call chain: 11252747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->dispatch_table.DestroySurfaceKHR(instance, surface, pAllocator); 11253747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes } 11254747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 11255747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 112566f2ed666809272002a31b3b4f8adf6581cb41819Norbert NopperVKAPI_ATTR VkResult VKAPI_CALL CreateDisplayPlaneSurfaceKHR(VkInstance instance, const VkDisplaySurfaceCreateInfoKHR *pCreateInfo, 112576f2ed666809272002a31b3b4f8adf6581cb41819Norbert Nopper const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) { 112586f2ed666809272002a31b3b4f8adf6581cb41819Norbert Nopper return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateDisplayPlaneSurfaceKHR); 112596f2ed666809272002a31b3b4f8adf6581cb41819Norbert Nopper} 112606f2ed666809272002a31b3b4f8adf6581cb41819Norbert Nopper 11261747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_ANDROID_KHR 11262747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR *pCreateInfo, 11263747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) { 11264747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateAndroidSurfaceKHR); 11265747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 11266cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_ANDROID_KHR 11267747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11268747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_MIR_KHR 11269747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateMirSurfaceKHR(VkInstance instance, const VkMirSurfaceCreateInfoKHR *pCreateInfo, 11270747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) { 11271747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateMirSurfaceKHR); 11272747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 11273cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_MIR_KHR 11274747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11275747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_WAYLAND_KHR 11276747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateWaylandSurfaceKHR(VkInstance instance, const VkWaylandSurfaceCreateInfoKHR *pCreateInfo, 11277747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) { 11278a9c6cc532ce0ef61d48d1419a96aae51b0e4c64aTobin Ehlis return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateWaylandSurfaceKHR); 11279747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 11280cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_WAYLAND_KHR 11281747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11282747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_WIN32_KHR 11283747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateWin32SurfaceKHR(VkInstance instance, const VkWin32SurfaceCreateInfoKHR *pCreateInfo, 11284747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) { 11285747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateWin32SurfaceKHR); 11286747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 11287cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_WIN32_KHR 11288747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11289747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_XCB_KHR 11290747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateXcbSurfaceKHR(VkInstance instance, const VkXcbSurfaceCreateInfoKHR *pCreateInfo, 11291747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) { 11292747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateXcbSurfaceKHR); 11293747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 11294cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_XCB_KHR 11295747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11296747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_XLIB_KHR 11297747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateXlibSurfaceKHR(VkInstance instance, const VkXlibSurfaceCreateInfoKHR *pCreateInfo, 11298bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) { 11299747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateXlibSurfaceKHR); 11300747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 11301cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_XLIB_KHR 11302747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 1130340921785005eb449ec7c18229f0d84c879708b8aChris ForbesVKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, 1130440921785005eb449ec7c18229f0d84c879708b8aChris Forbes VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) { 1130556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis auto instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 1130640921785005eb449ec7c18229f0d84c879708b8aChris Forbes 1130740921785005eb449ec7c18229f0d84c879708b8aChris Forbes std::unique_lock<std::mutex> lock(global_lock); 113089a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto physical_device_state = GetPhysicalDeviceState(instance_data, physicalDevice); 1130940921785005eb449ec7c18229f0d84c879708b8aChris Forbes lock.unlock(); 1131040921785005eb449ec7c18229f0d84c879708b8aChris Forbes 11311bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto result = 11312bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski instance_data->dispatch_table.GetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, pSurfaceCapabilities); 1131340921785005eb449ec7c18229f0d84c879708b8aChris Forbes 1131440921785005eb449ec7c18229f0d84c879708b8aChris Forbes if (result == VK_SUCCESS) { 1131540921785005eb449ec7c18229f0d84c879708b8aChris Forbes physical_device_state->vkGetPhysicalDeviceSurfaceCapabilitiesKHRState = QUERY_DETAILS; 1131640921785005eb449ec7c18229f0d84c879708b8aChris Forbes physical_device_state->surfaceCapabilities = *pSurfaceCapabilities; 1131740921785005eb449ec7c18229f0d84c879708b8aChris Forbes } 1131840921785005eb449ec7c18229f0d84c879708b8aChris Forbes 1131940921785005eb449ec7c18229f0d84c879708b8aChris Forbes return result; 1132040921785005eb449ec7c18229f0d84c879708b8aChris Forbes} 1132140921785005eb449ec7c18229f0d84c879708b8aChris Forbes 11322418a8711f3301f3027a900bb45daaf0892f4e644Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, 11323418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes VkSurfaceKHR surface, VkBool32 *pSupported) { 1132456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis auto instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 11325418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes std::unique_lock<std::mutex> lock(global_lock); 113269a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto surface_state = GetSurfaceState(instance_data, surface); 11327418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes lock.unlock(); 11328418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes 11329bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto result = 11330bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski instance_data->dispatch_table.GetPhysicalDeviceSurfaceSupportKHR(physicalDevice, queueFamilyIndex, surface, pSupported); 11331418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes 11332418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes if (result == VK_SUCCESS) { 113336569ab421f45f905e69fa7345bda4fe5b87e9045Mark Lobodzinski surface_state->gpu_queue_support[{physicalDevice, queueFamilyIndex}] = (*pSupported != 0); 11334418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes } 11335418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes 11336418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes return result; 11337418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes} 11338418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes 113399e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, 113409e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes uint32_t *pPresentModeCount, 113419e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes VkPresentModeKHR *pPresentModes) { 113429e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes bool skip_call = false; 1134356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis auto instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 113449e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes std::unique_lock<std::mutex> lock(global_lock); 113459e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes // TODO: this isn't quite right. available modes may differ by surface AND physical device. 113469a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto physical_device_state = GetPhysicalDeviceState(instance_data, physicalDevice); 11347bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto &call_state = physical_device_state->vkGetPhysicalDeviceSurfacePresentModesKHRState; 113489e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes 113499e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (pPresentModes) { 113509e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes // Compare the preliminary value of *pPresentModeCount with the value this time: 11351bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto prev_mode_count = (uint32_t)physical_device_state->present_modes.size(); 113529e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes switch (call_state) { 11353cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case UNCALLED: 113549e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes skip_call |= log_msg( 11355bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 11356cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski reinterpret_cast<uint64_t>(physicalDevice), __LINE__, DEVLIMITS_MUST_QUERY_COUNT, "DL", 11357cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkGetPhysicalDeviceSurfacePresentModesKHR() called with non-NULL pPresentModeCount; but no prior positive " 11358cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "value has been seen for pPresentModeCount."); 11359cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 11360cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 11361cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // both query count and query details 11362cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (*pPresentModeCount != prev_mode_count) { 11363cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski skip_call |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, 11364cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 11365cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski reinterpret_cast<uint64_t>(physicalDevice), __LINE__, DEVLIMITS_COUNT_MISMATCH, "DL", 11366cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkGetPhysicalDeviceSurfacePresentModesKHR() called with *pPresentModeCount (%u) that " 11367cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "differs from the value " 11368cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "(%u) that was returned when pPresentModes was NULL.", 11369cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski *pPresentModeCount, prev_mode_count); 11370cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 11371cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 113729e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 113739e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 113749e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes lock.unlock(); 113759e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes 11376cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip_call) return VK_ERROR_VALIDATION_FAILED_EXT; 113779e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes 11378bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto result = instance_data->dispatch_table.GetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, pPresentModeCount, 11379bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pPresentModes); 113809e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes 113819e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (result == VK_SUCCESS || result == VK_INCOMPLETE) { 113829e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes lock.lock(); 113839e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes 113849e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (*pPresentModeCount) { 11385cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (call_state < QUERY_COUNT) call_state = QUERY_COUNT; 113869e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (*pPresentModeCount > physical_device_state->present_modes.size()) 113879e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes physical_device_state->present_modes.resize(*pPresentModeCount); 113889e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 113899e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (pPresentModes) { 11390cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (call_state < QUERY_DETAILS) call_state = QUERY_DETAILS; 113919e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes for (uint32_t i = 0; i < *pPresentModeCount; i++) { 113929e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes physical_device_state->present_modes[i] = pPresentModes[i]; 113939e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 113949e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 113955faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 113965faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes 113975faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes return result; 113985faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes} 113995faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes 114005faa662f6859b01c72d79027abde363d5f10dcd7Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, 114015faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes uint32_t *pSurfaceFormatCount, 114025faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes VkSurfaceFormatKHR *pSurfaceFormats) { 114035faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes bool skip_call = false; 1140456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis auto instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 114055faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes std::unique_lock<std::mutex> lock(global_lock); 114069a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto physical_device_state = GetPhysicalDeviceState(instance_data, physicalDevice); 11407bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto &call_state = physical_device_state->vkGetPhysicalDeviceSurfaceFormatsKHRState; 114085faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes 114095faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (pSurfaceFormats) { 11410bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto prev_format_count = (uint32_t)physical_device_state->surface_formats.size(); 114115faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes 114125faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes switch (call_state) { 11413cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case UNCALLED: 11414cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Since we haven't recorded a preliminary value of *pSurfaceFormatCount, that likely means that the application 11415cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // didn't 11416cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // previously call this function with a NULL value of pSurfaceFormats: 114175faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes skip_call |= log_msg( 11418bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 11419cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski reinterpret_cast<uint64_t>(physicalDevice), __LINE__, DEVLIMITS_MUST_QUERY_COUNT, "DL", 11420cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkGetPhysicalDeviceSurfaceFormatsKHR() called with non-NULL pSurfaceFormatCount; but no prior positive " 11421cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "value has been seen for pSurfaceFormats."); 11422cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 11423cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 11424cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (prev_format_count != *pSurfaceFormatCount) { 11425cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski skip_call |= log_msg( 11426cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, 11427cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, reinterpret_cast<uint64_t>(physicalDevice), __LINE__, 11428cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski DEVLIMITS_COUNT_MISMATCH, "DL", 11429cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkGetPhysicalDeviceSurfaceFormatsKHR() called with non-NULL pSurfaceFormatCount, and with pSurfaceFormats " 11430cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "set " 11431cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "to " 11432cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "a value (%u) that is greater than the value (%u) that was returned when pSurfaceFormatCount was NULL.", 11433cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski *pSurfaceFormatCount, prev_format_count); 11434cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 11435cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 114369e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 114379e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 114385faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes lock.unlock(); 114395faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes 11440cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip_call) return VK_ERROR_VALIDATION_FAILED_EXT; 114419e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes 114425faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes // Call down the call chain: 114435faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes auto result = instance_data->dispatch_table.GetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, pSurfaceFormatCount, 114445faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes pSurfaceFormats); 114455faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes 114465faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (result == VK_SUCCESS || result == VK_INCOMPLETE) { 114475faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes lock.lock(); 114485faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes 114495faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (*pSurfaceFormatCount) { 11450cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (call_state < QUERY_COUNT) call_state = QUERY_COUNT; 114515faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (*pSurfaceFormatCount > physical_device_state->surface_formats.size()) 114525faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes physical_device_state->surface_formats.resize(*pSurfaceFormatCount); 114535faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 114545faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (pSurfaceFormats) { 11455cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (call_state < QUERY_DETAILS) call_state = QUERY_DETAILS; 114565faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes for (uint32_t i = 0; i < *pSurfaceFormatCount; i++) { 114575faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes physical_device_state->surface_formats[i] = pSurfaceFormats[i]; 114585faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 114595faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 114605faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 114619e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes return result; 114629e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes} 114639e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes 11464bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateDebugReportCallbackEXT(VkInstance instance, 11465bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkDebugReportCallbackCreateInfoEXT *pCreateInfo, 11466bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, 11467bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDebugReportCallbackEXT *pMsgCallback) { 1146856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 114699172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes VkResult res = instance_data->dispatch_table.CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback); 114705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == res) { 11471b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 114728860b85a52096f9f9b28616bc37feed505497a54Chris Forbes res = layer_create_msg_callback(instance_data->report_data, false, pCreateInfo, pAllocator, pMsgCallback); 114735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 114745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return res; 114755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 114765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 11477bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT msgCallback, 1147889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator) { 1147956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 114809172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes instance_data->dispatch_table.DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator); 11481b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 114828860b85a52096f9f9b28616bc37feed505497a54Chris Forbes layer_destroy_msg_callback(instance_data->report_data, msgCallback, pAllocator); 114835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 114845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 11485bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, 11486bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDebugReportObjectTypeEXT objType, uint64_t object, size_t location, 11487bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski int32_t msgCode, const char *pLayerPrefix, const char *pMsg) { 1148856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 114899172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes instance_data->dispatch_table.DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg); 114905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 114915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 11492bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) { 11493a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu return util_GetLayerProperties(1, &global_layer, pCount, pProperties); 11494a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu} 11495a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu 11496bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, 11497bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkLayerProperties *pProperties) { 11498a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu return util_GetLayerProperties(1, &global_layer, pCount, pProperties); 11499a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu} 11500a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu 11501bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, 11502bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkExtensionProperties *pProperties) { 11503a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) 11504a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties); 11505a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu 11506a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu return VK_ERROR_LAYER_NOT_PRESENT; 11507a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu} 11508a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu 11509bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName, 11510bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski uint32_t *pCount, VkExtensionProperties *pProperties) { 11511cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(0, NULL, pCount, pProperties); 11512a8f4a23b1e9c068717eda47cc583a93f447c77e3Chia-I Wu 11513a8f4a23b1e9c068717eda47cc583a93f447c77e3Chia-I Wu assert(physicalDevice); 11514a8f4a23b1e9c068717eda47cc583a93f447c77e3Chia-I Wu 1151556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 115169172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes return instance_data->dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties); 1151708939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu} 1151808939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu 11519582b6ed09649188d55ed3b6237352caf9f3384a9Mike WeiblenVKAPI_ATTR VkResult VKAPI_CALL EnumeratePhysicalDeviceGroupsKHX( 11520582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen VkInstance instance, uint32_t *pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupPropertiesKHX *pPhysicalDeviceGroupProperties) { 11521582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen bool skip_call = false; 11522582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 11523582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen 11524582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen if (instance_data) { 11525582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen // For this instance, flag when EnumeratePhysicalDeviceGroupsKHX goes to QUERY_COUNT and then QUERY_DETAILS. 11526582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen if (NULL == pPhysicalDeviceGroupProperties) { 11527582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen instance_data->vkEnumeratePhysicalDeviceGroupsState = QUERY_COUNT; 11528582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen } else { 11529582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen if (UNCALLED == instance_data->vkEnumeratePhysicalDeviceGroupsState) { 11530582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen // Flag warning here. You can call this without having queried the count, but it may not be 11531582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen // robust on platforms with multiple physical devices. 11532582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen skip_call |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, 11533582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, 0, __LINE__, DEVLIMITS_MISSING_QUERY_COUNT, "DL", 11534582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen "Call sequence has vkEnumeratePhysicalDeviceGroupsKHX() w/ non-NULL " 11535582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen "pPhysicalDeviceGroupProperties. You should first " 11536582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen "call vkEnumeratePhysicalDeviceGroupsKHX() w/ NULL pPhysicalDeviceGroupProperties to query " 11537582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen "pPhysicalDeviceGroupCount."); 11538582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen } // TODO : Could also flag a warning if re-calling this function in QUERY_DETAILS state 11539582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen else if (instance_data->physical_device_groups_count != *pPhysicalDeviceGroupCount) { 11540582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen // Having actual count match count from app is not a requirement, so this can be a warning 11541582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen skip_call |= 11542582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, 11543582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_COUNT_MISMATCH, "DL", 11544582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen "Call to vkEnumeratePhysicalDeviceGroupsKHX() w/ pPhysicalDeviceGroupCount value %u, but actual count " 11545582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen "supported by this instance is %u.", 11546582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen *pPhysicalDeviceGroupCount, instance_data->physical_device_groups_count); 11547582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen } 11548582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen instance_data->vkEnumeratePhysicalDeviceGroupsState = QUERY_DETAILS; 11549582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen } 11550582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen if (skip_call) { 11551582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen return VK_ERROR_VALIDATION_FAILED_EXT; 11552582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen } 11553582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen VkResult result = instance_data->dispatch_table.EnumeratePhysicalDeviceGroupsKHX(instance, pPhysicalDeviceGroupCount, 11554582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen pPhysicalDeviceGroupProperties); 11555582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen if (NULL == pPhysicalDeviceGroupProperties) { 11556582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen instance_data->physical_device_groups_count = *pPhysicalDeviceGroupCount; 11557582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen } else if (result == VK_SUCCESS) { // Save physical devices 11558582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen for (uint32_t i = 0; i < *pPhysicalDeviceGroupCount; i++) { 11559582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen for (uint32_t j = 0; j < pPhysicalDeviceGroupProperties[i].physicalDeviceCount; j++) { 11560582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen VkPhysicalDevice cur_phys_dev = pPhysicalDeviceGroupProperties[i].physicalDevices[j]; 11561582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen auto &phys_device_state = instance_data->physical_device_map[cur_phys_dev]; 11562582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen phys_device_state.phys_device = cur_phys_dev; 11563582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen // Init actual features for each physical device 11564582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen instance_data->dispatch_table.GetPhysicalDeviceFeatures(cur_phys_dev, &phys_device_state.features); 11565582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen } 11566582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen } 11567582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen } 11568582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen return result; 11569582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen } else { 11570582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen log_msg(instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, 0, __LINE__, 11571582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen DEVLIMITS_INVALID_INSTANCE, "DL", 11572582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen "Invalid instance (0x%" PRIxLEAST64 ") passed into vkEnumeratePhysicalDeviceGroupsKHX().", (uint64_t)instance); 11573582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen } 11574582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen return VK_ERROR_VALIDATION_FAILED_EXT; 11575582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen} 11576582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen 115776246f8feba03ddc787c31b3daa6a50d4ef01024fMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateDescriptorUpdateTemplateKHR(VkDevice device, 115786246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski const VkDescriptorUpdateTemplateCreateInfoKHR *pCreateInfo, 115796246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski const VkAllocationCallbacks *pAllocator, 115806246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski VkDescriptorUpdateTemplateKHR *pDescriptorUpdateTemplate) { 115816246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 11582a538cd4fff983b172362b0bba58f984124481a1cMark Lobodzinski VkResult result = 11583a538cd4fff983b172362b0bba58f984124481a1cMark Lobodzinski dev_data->dispatch_table.CreateDescriptorUpdateTemplateKHR(device, pCreateInfo, pAllocator, pDescriptorUpdateTemplate); 115846246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski if (VK_SUCCESS == result) { 115856246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski std::lock_guard<std::mutex> lock(global_lock); 115866246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski // Shadow template createInfo for later updates 11587a538cd4fff983b172362b0bba58f984124481a1cMark Lobodzinski safe_VkDescriptorUpdateTemplateCreateInfoKHR *local_create_info = 11588a538cd4fff983b172362b0bba58f984124481a1cMark Lobodzinski new safe_VkDescriptorUpdateTemplateCreateInfoKHR(pCreateInfo); 115896246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski std::unique_ptr<TEMPLATE_STATE> template_state(new TEMPLATE_STATE(*pDescriptorUpdateTemplate, local_create_info)); 115906246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski dev_data->desc_template_map[*pDescriptorUpdateTemplate] = std::move(template_state); 115916246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski } 115926246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski return result; 115936246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski} 115946246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski 115956246f8feba03ddc787c31b3daa6a50d4ef01024fMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyDescriptorUpdateTemplateKHR(VkDevice device, 115966246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate, 115976246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski const VkAllocationCallbacks *pAllocator) { 115986246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 115996246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski std::unique_lock<std::mutex> lock(global_lock); 116006246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski dev_data->desc_template_map.erase(descriptorUpdateTemplate); 116016246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski lock.unlock(); 116026246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski dev_data->dispatch_table.DestroyDescriptorUpdateTemplateKHR(device, descriptorUpdateTemplate, pAllocator); 116036246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski} 116046246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski 1160525f3712aed1cebdcb7c92eb25c5f1cc6e5986ac4Mark Lobodzinski// PostCallRecord* handles recording state updates following call down chain to UpdateDescriptorSetsWithTemplate() 1160625f3712aed1cebdcb7c92eb25c5f1cc6e5986ac4Mark Lobodzinskistatic void PostCallRecordUpdateDescriptorSetWithTemplateKHR(layer_data *device_data, VkDescriptorSet descriptorSet, 1160725f3712aed1cebdcb7c92eb25c5f1cc6e5986ac4Mark Lobodzinski VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate, 1160825f3712aed1cebdcb7c92eb25c5f1cc6e5986ac4Mark Lobodzinski const void *pData) { 1160967fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski auto const template_map_entry = device_data->desc_template_map.find(descriptorUpdateTemplate); 1161067fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski if (template_map_entry == device_data->desc_template_map.end()) { 1161167fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski assert(0); 1161267fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski } 1161367fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski 1161425f3712aed1cebdcb7c92eb25c5f1cc6e5986ac4Mark Lobodzinski cvdescriptorset::PerformUpdateDescriptorSetsWithTemplateKHR(device_data, descriptorSet, template_map_entry->second, pData); 1161567fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski} 1161667fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski 116176246f8feba03ddc787c31b3daa6a50d4ef01024fMark LobodzinskiVKAPI_ATTR void VKAPI_CALL UpdateDescriptorSetWithTemplateKHR(VkDevice device, VkDescriptorSet descriptorSet, 116186246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate, 116196246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski const void *pData) { 1162067fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski layer_data *device_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 1162167fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski device_data->dispatch_table.UpdateDescriptorSetWithTemplateKHR(device, descriptorSet, descriptorUpdateTemplate, pData); 1162267fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski 1162367fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski PostCallRecordUpdateDescriptorSetWithTemplateKHR(device_data, descriptorSet, descriptorUpdateTemplate, pData); 116246246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski} 116256246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski 116266246f8feba03ddc787c31b3daa6a50d4ef01024fMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdPushDescriptorSetWithTemplateKHR(VkCommandBuffer commandBuffer, 116276246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate, 116286246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski VkPipelineLayout layout, uint32_t set, const void *pData) { 116296246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 116306246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski dev_data->dispatch_table.CmdPushDescriptorSetWithTemplateKHR(commandBuffer, descriptorUpdateTemplate, layout, set, pData); 116316246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski} 116326246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski 11633bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic PFN_vkVoidFunction intercept_core_instance_command(const char *name); 116347ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu 11635bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic PFN_vkVoidFunction intercept_core_device_command(const char *name); 1163680be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu 116376246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinskistatic PFN_vkVoidFunction intercept_device_extension_command(const char *name, VkDevice device); 116386246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski 11639bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic PFN_vkVoidFunction intercept_khr_swapchain_command(const char *name, VkDevice dev); 1164009a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu 11641bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic PFN_vkVoidFunction intercept_khr_surface_command(const char *name, VkInstance instance); 11642747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11643582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblenstatic PFN_vkVoidFunction 11644582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblenintercept_extension_instance_commands(const char *name, VkInstance instance); 11645b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 1164689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice dev, const char *funcName) { 1164780be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu assert(dev); 116485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 116496246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski PFN_vkVoidFunction proc = intercept_core_device_command(funcName); 116506246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski if (!proc) proc = intercept_device_extension_command(funcName, dev); 116516246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski if (!proc) proc = intercept_khr_swapchain_command(funcName, dev); 11652cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (proc) return proc; 1165309a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu 1165456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(dev), layer_data_map); 116554a0754042cf090e131e9e769d8a3633c228625beChris Forbes auto &table = dev_data->dispatch_table; 11656cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!table.GetDeviceProcAddr) return nullptr; 116574a0754042cf090e131e9e769d8a3633c228625beChris Forbes return table.GetDeviceProcAddr(dev, funcName); 116585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 116595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1166089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) { 116617ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu PFN_vkVoidFunction proc = intercept_core_instance_command(funcName); 11662cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!proc) proc = intercept_core_device_command(funcName); 11663cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!proc) proc = intercept_khr_swapchain_command(funcName, VK_NULL_HANDLE); 11664cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!proc) proc = intercept_khr_surface_command(funcName, instance); 11665cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (proc) return proc; 116665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 116677ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu assert(instance); 116685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1166956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 116708860b85a52096f9f9b28616bc37feed505497a54Chris Forbes proc = debug_report_get_instance_proc_addr(instance_data->report_data, funcName); 11671cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (proc) return proc; 116725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 11673b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young proc = intercept_extension_instance_commands(funcName, instance); 11674cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (proc) return proc; 11675b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 116764a0754042cf090e131e9e769d8a3633c228625beChris Forbes auto &table = instance_data->dispatch_table; 11677cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!table.GetInstanceProcAddr) return nullptr; 116784a0754042cf090e131e9e769d8a3633c228625beChris Forbes return table.GetInstanceProcAddr(instance, funcName); 116795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 1168008939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu 11681b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark YoungVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetPhysicalDeviceProcAddr(VkInstance instance, const char *funcName) { 11682b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young assert(instance); 11683b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 1168456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 11685b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 11686b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young auto &table = instance_data->dispatch_table; 11687cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!table.GetPhysicalDeviceProcAddr) return nullptr; 11688b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young return table.GetPhysicalDeviceProcAddr(instance, funcName); 11689b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young} 11690b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 11691bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic PFN_vkVoidFunction intercept_core_instance_command(const char *name) { 116927ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu static const struct { 116937ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu const char *name; 116947ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu PFN_vkVoidFunction proc; 116957ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu } core_instance_commands[] = { 11696bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkGetInstanceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr)}, 11697bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vk_layerGetPhysicalDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceProcAddr)}, 11698bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkGetDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr)}, 11699bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkCreateInstance", reinterpret_cast<PFN_vkVoidFunction>(CreateInstance)}, 11700bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkCreateDevice", reinterpret_cast<PFN_vkVoidFunction>(CreateDevice)}, 11701bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkEnumeratePhysicalDevices", reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDevices)}, 11702bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkGetPhysicalDeviceQueueFamilyProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceQueueFamilyProperties)}, 11703bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance)}, 11704bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkEnumerateInstanceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceLayerProperties)}, 11705bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkEnumerateDeviceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceLayerProperties)}, 11706bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkEnumerateInstanceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceExtensionProperties)}, 11707bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkEnumerateDeviceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceExtensionProperties)}, 117087ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu }; 117097ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu 117107ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu for (size_t i = 0; i < ARRAY_SIZE(core_instance_commands); i++) { 11711cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!strcmp(core_instance_commands[i].name, name)) return core_instance_commands[i].proc; 117127ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu } 117137ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu 117147ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu return nullptr; 117157ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu} 117167ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu 11717bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic PFN_vkVoidFunction intercept_core_device_command(const char *name) { 1171880be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu static const struct { 1171980be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu const char *name; 1172080be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu PFN_vkVoidFunction proc; 1172180be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu } core_device_commands[] = { 11722593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkGetDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr)}, 11723593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkQueueSubmit", reinterpret_cast<PFN_vkVoidFunction>(QueueSubmit)}, 11724593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkWaitForFences", reinterpret_cast<PFN_vkVoidFunction>(WaitForFences)}, 11725593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkGetFenceStatus", reinterpret_cast<PFN_vkVoidFunction>(GetFenceStatus)}, 11726593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkQueueWaitIdle", reinterpret_cast<PFN_vkVoidFunction>(QueueWaitIdle)}, 11727593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDeviceWaitIdle", reinterpret_cast<PFN_vkVoidFunction>(DeviceWaitIdle)}, 11728593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkGetDeviceQueue", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceQueue)}, 11729593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance)}, 11730593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyDevice", reinterpret_cast<PFN_vkVoidFunction>(DestroyDevice)}, 11731593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyFence", reinterpret_cast<PFN_vkVoidFunction>(DestroyFence)}, 11732593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkResetFences", reinterpret_cast<PFN_vkVoidFunction>(ResetFences)}, 11733593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroySemaphore", reinterpret_cast<PFN_vkVoidFunction>(DestroySemaphore)}, 11734593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyEvent", reinterpret_cast<PFN_vkVoidFunction>(DestroyEvent)}, 11735593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyQueryPool", reinterpret_cast<PFN_vkVoidFunction>(DestroyQueryPool)}, 11736593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyBuffer", reinterpret_cast<PFN_vkVoidFunction>(DestroyBuffer)}, 11737593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyBufferView", reinterpret_cast<PFN_vkVoidFunction>(DestroyBufferView)}, 11738593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyImage", reinterpret_cast<PFN_vkVoidFunction>(DestroyImage)}, 11739593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyImageView", reinterpret_cast<PFN_vkVoidFunction>(DestroyImageView)}, 11740593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyShaderModule", reinterpret_cast<PFN_vkVoidFunction>(DestroyShaderModule)}, 11741593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyPipeline", reinterpret_cast<PFN_vkVoidFunction>(DestroyPipeline)}, 11742593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyPipelineLayout", reinterpret_cast<PFN_vkVoidFunction>(DestroyPipelineLayout)}, 11743593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroySampler", reinterpret_cast<PFN_vkVoidFunction>(DestroySampler)}, 11744593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyDescriptorSetLayout", reinterpret_cast<PFN_vkVoidFunction>(DestroyDescriptorSetLayout)}, 11745593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(DestroyDescriptorPool)}, 11746593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyFramebuffer", reinterpret_cast<PFN_vkVoidFunction>(DestroyFramebuffer)}, 11747593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyRenderPass", reinterpret_cast<PFN_vkVoidFunction>(DestroyRenderPass)}, 11748593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateBuffer", reinterpret_cast<PFN_vkVoidFunction>(CreateBuffer)}, 11749593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateBufferView", reinterpret_cast<PFN_vkVoidFunction>(CreateBufferView)}, 11750593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateImage", reinterpret_cast<PFN_vkVoidFunction>(CreateImage)}, 11751593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateImageView", reinterpret_cast<PFN_vkVoidFunction>(CreateImageView)}, 11752593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateFence", reinterpret_cast<PFN_vkVoidFunction>(CreateFence)}, 11753593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreatePipelineCache", reinterpret_cast<PFN_vkVoidFunction>(CreatePipelineCache)}, 11754593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyPipelineCache", reinterpret_cast<PFN_vkVoidFunction>(DestroyPipelineCache)}, 11755593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkGetPipelineCacheData", reinterpret_cast<PFN_vkVoidFunction>(GetPipelineCacheData)}, 11756593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkMergePipelineCaches", reinterpret_cast<PFN_vkVoidFunction>(MergePipelineCaches)}, 11757593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateGraphicsPipelines", reinterpret_cast<PFN_vkVoidFunction>(CreateGraphicsPipelines)}, 11758593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateComputePipelines", reinterpret_cast<PFN_vkVoidFunction>(CreateComputePipelines)}, 11759593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateSampler", reinterpret_cast<PFN_vkVoidFunction>(CreateSampler)}, 11760593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateDescriptorSetLayout", reinterpret_cast<PFN_vkVoidFunction>(CreateDescriptorSetLayout)}, 11761593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreatePipelineLayout", reinterpret_cast<PFN_vkVoidFunction>(CreatePipelineLayout)}, 11762593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(CreateDescriptorPool)}, 11763593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkResetDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(ResetDescriptorPool)}, 11764593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkAllocateDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(AllocateDescriptorSets)}, 11765593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkFreeDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(FreeDescriptorSets)}, 11766593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkUpdateDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(UpdateDescriptorSets)}, 11767593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateCommandPool", reinterpret_cast<PFN_vkVoidFunction>(CreateCommandPool)}, 11768593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyCommandPool", reinterpret_cast<PFN_vkVoidFunction>(DestroyCommandPool)}, 11769593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkResetCommandPool", reinterpret_cast<PFN_vkVoidFunction>(ResetCommandPool)}, 11770593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateQueryPool", reinterpret_cast<PFN_vkVoidFunction>(CreateQueryPool)}, 11771593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkAllocateCommandBuffers", reinterpret_cast<PFN_vkVoidFunction>(AllocateCommandBuffers)}, 11772593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkFreeCommandBuffers", reinterpret_cast<PFN_vkVoidFunction>(FreeCommandBuffers)}, 11773593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkBeginCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(BeginCommandBuffer)}, 11774593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkEndCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(EndCommandBuffer)}, 11775593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkResetCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(ResetCommandBuffer)}, 11776593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdBindPipeline", reinterpret_cast<PFN_vkVoidFunction>(CmdBindPipeline)}, 11777593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdSetViewport", reinterpret_cast<PFN_vkVoidFunction>(CmdSetViewport)}, 11778593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdSetScissor", reinterpret_cast<PFN_vkVoidFunction>(CmdSetScissor)}, 11779593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdSetLineWidth", reinterpret_cast<PFN_vkVoidFunction>(CmdSetLineWidth)}, 11780593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdSetDepthBias", reinterpret_cast<PFN_vkVoidFunction>(CmdSetDepthBias)}, 11781593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdSetBlendConstants", reinterpret_cast<PFN_vkVoidFunction>(CmdSetBlendConstants)}, 11782593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdSetDepthBounds", reinterpret_cast<PFN_vkVoidFunction>(CmdSetDepthBounds)}, 11783593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdSetStencilCompareMask", reinterpret_cast<PFN_vkVoidFunction>(CmdSetStencilCompareMask)}, 11784593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdSetStencilWriteMask", reinterpret_cast<PFN_vkVoidFunction>(CmdSetStencilWriteMask)}, 11785593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdSetStencilReference", reinterpret_cast<PFN_vkVoidFunction>(CmdSetStencilReference)}, 11786593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdBindDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(CmdBindDescriptorSets)}, 11787593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdBindVertexBuffers", reinterpret_cast<PFN_vkVoidFunction>(CmdBindVertexBuffers)}, 11788593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdBindIndexBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdBindIndexBuffer)}, 11789593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdDraw", reinterpret_cast<PFN_vkVoidFunction>(CmdDraw)}, 11790593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdDrawIndexed", reinterpret_cast<PFN_vkVoidFunction>(CmdDrawIndexed)}, 11791593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdDrawIndirect", reinterpret_cast<PFN_vkVoidFunction>(CmdDrawIndirect)}, 11792593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdDrawIndexedIndirect", reinterpret_cast<PFN_vkVoidFunction>(CmdDrawIndexedIndirect)}, 11793593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdDispatch", reinterpret_cast<PFN_vkVoidFunction>(CmdDispatch)}, 11794593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdDispatchIndirect", reinterpret_cast<PFN_vkVoidFunction>(CmdDispatchIndirect)}, 11795593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdCopyBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyBuffer)}, 11796593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdCopyImage", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyImage)}, 11797593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdBlitImage", reinterpret_cast<PFN_vkVoidFunction>(CmdBlitImage)}, 11798593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdCopyBufferToImage", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyBufferToImage)}, 11799593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdCopyImageToBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyImageToBuffer)}, 11800593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdUpdateBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdUpdateBuffer)}, 11801593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdFillBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdFillBuffer)}, 11802593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdClearColorImage", reinterpret_cast<PFN_vkVoidFunction>(CmdClearColorImage)}, 11803593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdClearDepthStencilImage", reinterpret_cast<PFN_vkVoidFunction>(CmdClearDepthStencilImage)}, 11804593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdClearAttachments", reinterpret_cast<PFN_vkVoidFunction>(CmdClearAttachments)}, 11805593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdResolveImage", reinterpret_cast<PFN_vkVoidFunction>(CmdResolveImage)}, 11806b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski {"vkGetImageSubresourceLayout", reinterpret_cast<PFN_vkVoidFunction>(GetImageSubresourceLayout) }, 11807593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdSetEvent", reinterpret_cast<PFN_vkVoidFunction>(CmdSetEvent)}, 11808593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdResetEvent", reinterpret_cast<PFN_vkVoidFunction>(CmdResetEvent)}, 11809593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdWaitEvents", reinterpret_cast<PFN_vkVoidFunction>(CmdWaitEvents)}, 11810593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdPipelineBarrier", reinterpret_cast<PFN_vkVoidFunction>(CmdPipelineBarrier)}, 11811593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdBeginQuery", reinterpret_cast<PFN_vkVoidFunction>(CmdBeginQuery)}, 11812593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdEndQuery", reinterpret_cast<PFN_vkVoidFunction>(CmdEndQuery)}, 11813593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdResetQueryPool", reinterpret_cast<PFN_vkVoidFunction>(CmdResetQueryPool)}, 11814593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdCopyQueryPoolResults", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyQueryPoolResults)}, 11815593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdPushConstants", reinterpret_cast<PFN_vkVoidFunction>(CmdPushConstants)}, 11816593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdWriteTimestamp", reinterpret_cast<PFN_vkVoidFunction>(CmdWriteTimestamp)}, 11817593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateFramebuffer", reinterpret_cast<PFN_vkVoidFunction>(CreateFramebuffer)}, 11818593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateShaderModule", reinterpret_cast<PFN_vkVoidFunction>(CreateShaderModule)}, 11819593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateRenderPass", reinterpret_cast<PFN_vkVoidFunction>(CreateRenderPass)}, 11820593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdBeginRenderPass", reinterpret_cast<PFN_vkVoidFunction>(CmdBeginRenderPass)}, 11821593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdNextSubpass", reinterpret_cast<PFN_vkVoidFunction>(CmdNextSubpass)}, 11822593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdEndRenderPass", reinterpret_cast<PFN_vkVoidFunction>(CmdEndRenderPass)}, 11823593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdExecuteCommands", reinterpret_cast<PFN_vkVoidFunction>(CmdExecuteCommands)}, 11824593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkSetEvent", reinterpret_cast<PFN_vkVoidFunction>(SetEvent)}, 11825593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkMapMemory", reinterpret_cast<PFN_vkVoidFunction>(MapMemory)}, 11826593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkUnmapMemory", reinterpret_cast<PFN_vkVoidFunction>(UnmapMemory)}, 11827593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkFlushMappedMemoryRanges", reinterpret_cast<PFN_vkVoidFunction>(FlushMappedMemoryRanges)}, 11828593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkInvalidateMappedMemoryRanges", reinterpret_cast<PFN_vkVoidFunction>(InvalidateMappedMemoryRanges)}, 11829593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkAllocateMemory", reinterpret_cast<PFN_vkVoidFunction>(AllocateMemory)}, 11830593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkFreeMemory", reinterpret_cast<PFN_vkVoidFunction>(FreeMemory)}, 11831593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkBindBufferMemory", reinterpret_cast<PFN_vkVoidFunction>(BindBufferMemory)}, 11832593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkGetBufferMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(GetBufferMemoryRequirements)}, 11833593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkGetImageMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(GetImageMemoryRequirements)}, 11834593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkGetQueryPoolResults", reinterpret_cast<PFN_vkVoidFunction>(GetQueryPoolResults)}, 11835593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkBindImageMemory", reinterpret_cast<PFN_vkVoidFunction>(BindImageMemory)}, 11836593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkQueueBindSparse", reinterpret_cast<PFN_vkVoidFunction>(QueueBindSparse)}, 11837593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateSemaphore", reinterpret_cast<PFN_vkVoidFunction>(CreateSemaphore)}, 11838593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateEvent", reinterpret_cast<PFN_vkVoidFunction>(CreateEvent)}, 1183980be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu }; 1184080be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu 1184180be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu for (size_t i = 0; i < ARRAY_SIZE(core_device_commands); i++) { 11842cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!strcmp(core_device_commands[i].name, name)) return core_device_commands[i].proc; 118436246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski } 118446246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski 118456246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski return nullptr; 118466246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski} 118476246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski 118486246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinskistatic PFN_vkVoidFunction intercept_device_extension_command(const char *name, VkDevice device) { 118496246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski layer_data *device_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 118506246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski 118516246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski const struct { 118526246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski const char *name; 118536246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski PFN_vkVoidFunction proc; 118546246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski bool enabled; 118556246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski } device_extension_commands[] = { 118566246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski {"vkCreateDescriptorUpdateTemplateKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateDescriptorUpdateTemplateKHR), 118576246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski device_data->device_extensions.khr_descriptor_update_template_enabled}, 118586246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski {"vkDestroyDescriptorUpdateTemplateKHR", reinterpret_cast<PFN_vkVoidFunction>(DestroyDescriptorUpdateTemplateKHR), 118596246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski device_data->device_extensions.khr_descriptor_update_template_enabled}, 118606246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski {"vkUpdateDescriptorSetWithTemplateKHR", reinterpret_cast<PFN_vkVoidFunction>(UpdateDescriptorSetWithTemplateKHR), 118616246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski device_data->device_extensions.khr_descriptor_update_template_enabled}, 118626246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski {"vkCmdPushDescriptorSetWithTemplateKHR", reinterpret_cast<PFN_vkVoidFunction>(CmdPushDescriptorSetWithTemplateKHR), 118636246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski device_data->device_extensions.khr_descriptor_update_template_enabled}, 118646246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski }; 118656246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski 118666246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski if (!device_data || !device_data->device_extensions.khr_descriptor_update_template_enabled) return nullptr; 118676246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski 118686246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski for (size_t i = 0; i < ARRAY_SIZE(device_extension_commands); i++) { 118696246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski if (!strcmp(device_extension_commands[i].name, name) && device_extension_commands[i].enabled) 118706246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski return device_extension_commands[i].proc; 1187180be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu } 1187280be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu 1187380be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu return nullptr; 1187480be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu} 1187580be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu 11876bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic PFN_vkVoidFunction intercept_khr_swapchain_command(const char *name, VkDevice dev) { 1187709a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu static const struct { 1187809a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu const char *name; 1187909a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu PFN_vkVoidFunction proc; 1188009a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu } khr_swapchain_commands[] = { 11881bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkCreateSwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateSwapchainKHR)}, 11882bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkDestroySwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(DestroySwapchainKHR)}, 11883bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkGetSwapchainImagesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetSwapchainImagesKHR)}, 11884bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkAcquireNextImageKHR", reinterpret_cast<PFN_vkVoidFunction>(AcquireNextImageKHR)}, 11885bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkQueuePresentKHR", reinterpret_cast<PFN_vkVoidFunction>(QueuePresentKHR)}, 1188609a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu }; 11887c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young layer_data *dev_data = nullptr; 1188809a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu 118893f6f8132355ebdae2736b31fc20de2ac60a70310Chia-I Wu if (dev) { 1189056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis dev_data = GetLayerDataPtr(get_dispatch_key(dev), layer_data_map); 11891cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!dev_data->device_extensions.wsi_enabled) return nullptr; 118923f6f8132355ebdae2736b31fc20de2ac60a70310Chia-I Wu } 1189309a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu 1189409a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu for (size_t i = 0; i < ARRAY_SIZE(khr_swapchain_commands); i++) { 11895cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!strcmp(khr_swapchain_commands[i].name, name)) return khr_swapchain_commands[i].proc; 1189609a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu } 1189709a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu 11898c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young if (dev_data) { 11899cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!dev_data->device_extensions.wsi_display_swapchain_enabled) return nullptr; 11900c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young } 11901c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young 11902cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!strcmp("vkCreateSharedSwapchainsKHR", name)) return reinterpret_cast<PFN_vkVoidFunction>(CreateSharedSwapchainsKHR); 11903c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young 1190409a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu return nullptr; 11905747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 11906747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11907bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic PFN_vkVoidFunction intercept_khr_surface_command(const char *name, VkInstance instance) { 11908747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes static const struct { 11909747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes const char *name; 11910747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes PFN_vkVoidFunction proc; 11911747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes bool instance_layer_data::*enable; 11912747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes } khr_surface_commands[] = { 11913747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_ANDROID_KHR 11914747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes {"vkCreateAndroidSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateAndroidSurfaceKHR), 11915bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::androidSurfaceExtensionEnabled}, 11916cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_ANDROID_KHR 11917747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_MIR_KHR 11918747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes {"vkCreateMirSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateMirSurfaceKHR), 11919bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::mirSurfaceExtensionEnabled}, 11920cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_MIR_KHR 11921747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_WAYLAND_KHR 11922747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes {"vkCreateWaylandSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateWaylandSurfaceKHR), 11923bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::waylandSurfaceExtensionEnabled}, 11924cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_WAYLAND_KHR 11925747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_WIN32_KHR 11926747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes {"vkCreateWin32SurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateWin32SurfaceKHR), 11927bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::win32SurfaceExtensionEnabled}, 11928cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_WIN32_KHR 11929747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_XCB_KHR 11930747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes {"vkCreateXcbSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateXcbSurfaceKHR), 11931bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::xcbSurfaceExtensionEnabled}, 11932cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_XCB_KHR 11933747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_XLIB_KHR 11934747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes {"vkCreateXlibSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateXlibSurfaceKHR), 11935bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::xlibSurfaceExtensionEnabled}, 11936cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_XLIB_KHR 11937bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkCreateDisplayPlaneSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateDisplayPlaneSurfaceKHR), 11938bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::displayExtensionEnabled}, 11939747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes {"vkDestroySurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(DestroySurfaceKHR), 11940bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::surfaceExtensionEnabled}, 1194140921785005eb449ec7c18229f0d84c879708b8aChris Forbes {"vkGetPhysicalDeviceSurfaceCapabilitiesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceCapabilitiesKHR), 11942bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::surfaceExtensionEnabled}, 11943418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes {"vkGetPhysicalDeviceSurfaceSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceSupportKHR), 11944bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::surfaceExtensionEnabled}, 119459e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes {"vkGetPhysicalDeviceSurfacePresentModesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfacePresentModesKHR), 11946bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::surfaceExtensionEnabled}, 119475faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes {"vkGetPhysicalDeviceSurfaceFormatsKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceFormatsKHR), 11948bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::surfaceExtensionEnabled}, 11949747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes }; 11950747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11951747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_layer_data *instance_data = nullptr; 11952747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (instance) { 1195356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 11954747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes } 11955747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11956747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes for (size_t i = 0; i < ARRAY_SIZE(khr_surface_commands); i++) { 11957747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (!strcmp(khr_surface_commands[i].name, name)) { 11958cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (instance_data && !(instance_data->*(khr_surface_commands[i].enable))) return nullptr; 11959747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes return khr_surface_commands[i].proc; 11960747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes } 11961747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes } 11962747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11963747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes return nullptr; 1196409a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu} 1196509a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu 1196643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic PFN_vkVoidFunction intercept_extension_instance_commands(const char *name, VkInstance instance) { 1196743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis static const struct { 1196843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis const char *name; 1196943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis PFN_vkVoidFunction proc; 1197043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis bool instance_layer_data::*enable; 1197143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } instance_extension_commands[] = { 1197243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis {"vkGetPhysicalDeviceQueueFamilyProperties2KHR", 1197343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceQueueFamilyProperties2KHR)}, 11974582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen {"vkEnumeratePhysicalDeviceGroupsKHX", 11975582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDeviceGroupsKHX)}, 1197643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis }; 1197743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis 1197843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis for (size_t i = 0; i < ARRAY_SIZE(instance_extension_commands); i++) { 1197943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis if (!strcmp(instance_extension_commands[i].name, name)) { 1198043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis return instance_extension_commands[i].proc; 1198143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 1198243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 1198343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis return nullptr; 1198443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis} 11985b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 11986cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski} // namespace core_validation 11987d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu 11988d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu// vk_layer_logging.h expects these to be defined 11989d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu 11990bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugReportCallbackEXT(VkInstance instance, 11991bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkDebugReportCallbackCreateInfoEXT *pCreateInfo, 11992bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, 11993bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDebugReportCallbackEXT *pMsgCallback) { 1199489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu return core_validation::CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback); 11995d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu} 11996d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu 11997bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT msgCallback, 11998bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator) { 1199989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu core_validation::DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator); 12000d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu} 12001d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu 12002bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL vkDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, 12003bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDebugReportObjectTypeEXT objType, uint64_t object, size_t location, 12004bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski int32_t msgCode, const char *pLayerPrefix, const char *pMsg) { 1200589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu core_validation::DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg); 12006d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu} 12007d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu 12008a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu// loader-layer interface v0, just wrappers since there is only a layer 12009d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu 12010bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, 12011bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkExtensionProperties *pProperties) { 12012a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu return core_validation::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties); 1201308939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu} 1201408939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu 12015bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount, 12016bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkLayerProperties *pProperties) { 12017a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu return core_validation::EnumerateInstanceLayerProperties(pCount, pProperties); 1201808939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu} 1201908939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu 12020bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, 12021bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkLayerProperties *pProperties) { 12022a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu // the layer command handles VK_NULL_HANDLE just fine internally 12023a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu assert(physicalDevice == VK_NULL_HANDLE); 12024a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu return core_validation::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties); 12025d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu} 12026d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu 12027d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I WuVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, 12028d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu const char *pLayerName, uint32_t *pCount, 12029d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu VkExtensionProperties *pProperties) { 12030a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu // the layer command handles VK_NULL_HANDLE just fine internally 12031a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu assert(physicalDevice == VK_NULL_HANDLE); 12032a8f4a23b1e9c068717eda47cc583a93f447c77e3Chia-I Wu return core_validation::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties); 12033d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu} 12034d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu 12035d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I WuVK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) { 1203689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu return core_validation::GetDeviceProcAddr(dev, funcName); 12037d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu} 12038d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu 12039d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I WuVK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) { 1204089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu return core_validation::GetInstanceProcAddr(instance, funcName); 1204108939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu} 12042b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 12043bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance, 12044bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const char *funcName) { 12045b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young return core_validation::GetPhysicalDeviceProcAddr(instance, funcName); 12046b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young} 12047b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 12048b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark YoungVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) { 12049b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young assert(pVersionStruct != NULL); 12050b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT); 12051b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 12052b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young // Fill in the function pointers if our version is at least capable of having the structure contain them. 12053b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young if (pVersionStruct->loaderLayerInterfaceVersion >= 2) { 12054b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr; 12055b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr; 12056b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young pVersionStruct->pfnGetPhysicalDeviceProcAddr = vk_layerGetPhysicalDeviceProcAddr; 12057b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young } 12058b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 12059b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young if (pVersionStruct->loaderLayerInterfaceVersion < CURRENT_LOADER_LAYER_INTERFACE_VERSION) { 12060b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young core_validation::loader_layer_if_version = pVersionStruct->loaderLayerInterfaceVersion; 12061b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young } else if (pVersionStruct->loaderLayerInterfaceVersion > CURRENT_LOADER_LAYER_INTERFACE_VERSION) { 12062b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young pVersionStruct->loaderLayerInterfaceVersion = CURRENT_LOADER_LAYER_INTERFACE_VERSION; 12063b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young } 12064b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 12065b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young return VK_SUCCESS; 12066b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young} 12067