core_validation.cpp revision e446ad08318228362ef35d73e7a0636075cb3636
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 4107a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinskistatic BINDABLE *GetObjectMemBinding(layer_data *dev_data, uint64_t handle, VulkanObjectType type) { 4115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis switch (type) { 4127a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski case kVulkanObjectTypeImage: 4139a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis return GetImageState(dev_data, VkImage(handle)); 4147a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski case kVulkanObjectTypeBuffer: 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 441cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis// For given bound_object_handle, bound to given mem allocation, verify that the range for the bound object is valid 4427a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinskistatic bool ValidateMemoryIsValid(layer_data *dev_data, VkDeviceMemory mem, uint64_t bound_object_handle, VulkanObjectType type, 4437a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski const char *functionName) { 4449a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *mem_info = GetMemObjInfo(dev_data, mem); 445f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis if (mem_info) { 446f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis if (!mem_info->bound_ranges[bound_object_handle].valid) { 447f48a83f5b5548cd46a12770c7542ff902537ad3eKarl Schultz return log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 448ea8e85ade623a09c601d939622cbd7740d8d66c9Tobin Ehlis reinterpret_cast<uint64_t &>(mem), __LINE__, MEMTRACK_INVALID_MEM_REGION, "MEM", 449dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis "%s: Cannot read invalid region of memory allocation 0x%" PRIx64 " for bound %s object 0x%" PRIx64 450dc21d4c322604e04e0b8433970f6a1ced6a0b647Tobin Ehlis ", please fill the memory before using.", 4517a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski functionName, reinterpret_cast<uint64_t &>(mem), object_string[type], bound_object_handle); 452f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis } 453f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis } 454f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis return false; 455f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis} 4561facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis// For given image_state 4571facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis// If mem is special swapchain key, then verify that image_state valid member is true 458f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis// Else verify that the image's bound memory range is valid 45960568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinskibool ValidateImageMemoryIsValid(layer_data *dev_data, IMAGE_STATE *image_state, const char *functionName) { 460e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis if (image_state->binding.mem == MEMTRACKER_SWAP_CHAIN_IMAGE_KEY) { 4611facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis if (!image_state->valid) { 462f48a83f5b5548cd46a12770c7542ff902537ad3eKarl Schultz return log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 463e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis reinterpret_cast<uint64_t &>(image_state->binding.mem), __LINE__, MEMTRACK_INVALID_MEM_REGION, "MEM", 464414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller "%s: Cannot read invalid swapchain image 0x%" PRIx64 ", please fill the memory before using.", 4651facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis functionName, reinterpret_cast<uint64_t &>(image_state->image)); 4665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 4675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 468e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis return ValidateMemoryIsValid(dev_data, image_state->binding.mem, reinterpret_cast<uint64_t &>(image_state->image), 4697a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski kVulkanObjectTypeImage, functionName); 4705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 4715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 4725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 4735cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis// For given buffer_state, verify that the range it's bound to is valid 474c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinskibool ValidateBufferMemoryIsValid(layer_data *dev_data, BUFFER_STATE *buffer_state, const char *functionName) { 4755cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis return ValidateMemoryIsValid(dev_data, buffer_state->binding.mem, reinterpret_cast<uint64_t &>(buffer_state->buffer), 4767a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski kVulkanObjectTypeBuffer, functionName); 477f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis} 478f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis// For the given memory allocation, set the range bound by the given handle object to the valid param value 479f989de4217bce0f293121d0da53dc8328276370fTobin Ehlisstatic void SetMemoryValid(layer_data *dev_data, VkDeviceMemory mem, uint64_t handle, bool valid) { 4809a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *mem_info = GetMemObjInfo(dev_data, mem); 481f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis if (mem_info) { 482f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis mem_info->bound_ranges[handle].valid = valid; 483f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis } 484f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis} 485f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis// For given image node 4861facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis// If mem is special swapchain key, then set entire image_state to valid param value 487f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis// Else set the image's bound memory range to valid param value 488623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinskivoid SetImageMemoryValid(layer_data *dev_data, IMAGE_STATE *image_state, bool valid) { 489e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis if (image_state->binding.mem == MEMTRACKER_SWAP_CHAIN_IMAGE_KEY) { 4901facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis image_state->valid = valid; 4915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 492e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis SetMemoryValid(dev_data, image_state->binding.mem, reinterpret_cast<uint64_t &>(image_state->image), valid); 4935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 4945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 495f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis// For given buffer node set the buffer's bound memory range to valid param value 496c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinskivoid SetBufferMemoryValid(layer_data *dev_data, BUFFER_STATE *buffer_state, bool valid) { 4975cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis SetMemoryValid(dev_data, buffer_state->binding.mem, reinterpret_cast<uint64_t &>(buffer_state->buffer), valid); 498f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis} 499ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis 50056f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis// Create binding link between given sampler and command buffer node 501d31a44af6da568692a73201825459689c9431867Tobin Ehlisvoid AddCommandBufferBindingSampler(GLOBAL_CB_NODE *cb_node, SAMPLER_STATE *sampler_state) { 502d31a44af6da568692a73201825459689c9431867Tobin Ehlis sampler_state->cb_bindings.insert(cb_node); 503d31a44af6da568692a73201825459689c9431867Tobin Ehlis cb_node->object_bindings.insert( 5047a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski {reinterpret_cast<uint64_t &>(sampler_state->sampler), kVulkanObjectTypeSampler }); 50556f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis} 50656f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis 50756f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis// Create binding link between given image node and command buffer node 5081facd2c91911508b9fb61f54a56269841299f663Tobin Ehlisvoid AddCommandBufferBindingImage(const layer_data *dev_data, GLOBAL_CB_NODE *cb_node, IMAGE_STATE *image_state) { 509ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis // Skip validation if this image was created through WSI 510e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis if (image_state->binding.mem != MEMTRACKER_SWAP_CHAIN_IMAGE_KEY) { 511ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis // First update CB binding in MemObj mini CB list 512d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis for (auto mem_binding : image_state->GetBoundMemory()) { 5139a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *pMemInfo = GetMemObjInfo(dev_data, mem_binding); 514d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis if (pMemInfo) { 515d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis pMemInfo->cb_bindings.insert(cb_node); 516d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis // Now update CBInfo's Mem reference list 517d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis cb_node->memObjs.insert(mem_binding); 518d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis } 519ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } 520f940225c9e5e3e14b3f5a32d3ea360b585614600Tobin Ehlis // Now update cb binding for image 5217a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski cb_node->object_bindings.insert({reinterpret_cast<uint64_t &>(image_state->image), kVulkanObjectTypeImage }); 5221facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis image_state->cb_bindings.insert(cb_node); 523ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } 524ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis} 525ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis 52603ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis// Create binding link between given image view node and its image with command buffer node 52703ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlisvoid AddCommandBufferBindingImageView(const layer_data *dev_data, GLOBAL_CB_NODE *cb_node, IMAGE_VIEW_STATE *view_state) { 52803ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis // First add bindings for imageView 52903ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis view_state->cb_bindings.insert(cb_node); 53003ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis cb_node->object_bindings.insert( 5317a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski {reinterpret_cast<uint64_t &>(view_state->image_view), kVulkanObjectTypeImageView }); 5329a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_state = GetImageState(dev_data, view_state->create_info.image); 53303ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis // Add bindings for image within imageView 5341facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis if (image_state) { 5351facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis AddCommandBufferBindingImage(dev_data, cb_node, image_state); 53603ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis } 53703ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis} 53803ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis 539ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis// Create binding link between given buffer node and command buffer node 5405cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlisvoid AddCommandBufferBindingBuffer(const layer_data *dev_data, GLOBAL_CB_NODE *cb_node, BUFFER_STATE *buffer_state) { 541ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis // First update CB binding in MemObj mini CB list 5425cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis for (auto mem_binding : buffer_state->GetBoundMemory()) { 5439a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *pMemInfo = GetMemObjInfo(dev_data, mem_binding); 544d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis if (pMemInfo) { 545d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis pMemInfo->cb_bindings.insert(cb_node); 546d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis // Now update CBInfo's Mem reference list 547d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis cb_node->memObjs.insert(mem_binding); 548d87d172d120ea3f00bfd34335537332d7ce61a89Tobin Ehlis } 549ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } 550ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis // Now update cb binding for buffer 5517a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski cb_node->object_bindings.insert({reinterpret_cast<uint64_t &>(buffer_state->buffer), kVulkanObjectTypeBuffer }); 5525cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis buffer_state->cb_bindings.insert(cb_node); 553ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis} 554ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis 55577b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis// Create binding link between given buffer view node and its buffer with command buffer node 55677b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlisvoid AddCommandBufferBindingBufferView(const layer_data *dev_data, GLOBAL_CB_NODE *cb_node, BUFFER_VIEW_STATE *view_state) { 55777b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis // First add bindings for bufferView 55877b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis view_state->cb_bindings.insert(cb_node); 55977b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis cb_node->object_bindings.insert( 5607a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski {reinterpret_cast<uint64_t &>(view_state->buffer_view), kVulkanObjectTypeBufferView }); 5619a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto buffer_state = GetBufferState(dev_data, view_state->create_info.buffer); 56277b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis // Add bindings for buffer within bufferView 5635cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis if (buffer_state) { 5645cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis AddCommandBufferBindingBuffer(dev_data, cb_node, buffer_state); 56577b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis } 56677b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis} 56777b6217754b9c167b08cb151e70b41a948e36277Tobin Ehlis 568400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis// For every mem obj bound to particular CB, free bindings related to that CB 569d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlisstatic void clear_cmd_buf_and_mem_references(layer_data *dev_data, GLOBAL_CB_NODE *cb_node) { 570d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis if (cb_node) { 571d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis if (cb_node->memObjs.size() > 0) { 572d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis for (auto mem : cb_node->memObjs) { 5739a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *pInfo = GetMemObjInfo(dev_data, mem); 5745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pInfo) { 575d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis pInfo->cb_bindings.erase(cb_node); 5765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 578d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis cb_node->memObjs.clear(); 5795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 580d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis cb_node->validate_functions.clear(); 5815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 5835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 584f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis// Clear a single object binding from given memory object, or report error if binding is missing 5857a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinskistatic bool ClearMemoryObjectBinding(layer_data *dev_data, uint64_t handle, VulkanObjectType type, VkDeviceMemory mem) { 5869a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *mem_info = GetMemObjInfo(dev_data, mem); 587f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis // This obj is bound to a memory object. Remove the reference to this object in that memory object's list 588d4cd34fd49caa759cf01cafa5fa271401b17c3b9Jeremy Hayes if (mem_info) { 589d4cd34fd49caa759cf01cafa5fa271401b17c3b9Jeremy Hayes mem_info->obj_bindings.erase({handle, type}); 590f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis } 591f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis return false; 592f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis} 593f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis 594f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis// ClearMemoryObjectBindings clears the binding of objects to memory 595f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis// For the given object it pulls the memory bindings and makes sure that the bindings 596f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis// no longer refer to the object being cleared. This occurs when objects are destroyed. 5977a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinskibool ClearMemoryObjectBindings(layer_data *dev_data, uint64_t handle, VulkanObjectType type) { 598f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis bool skip = false; 599f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis BINDABLE *mem_binding = GetObjectMemBinding(dev_data, handle, type); 600f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis if (mem_binding) { 601f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis if (!mem_binding->sparse) { 602f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis skip = ClearMemoryObjectBinding(dev_data, handle, type, mem_binding->binding.mem); 603cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else { // Sparse, clear all bindings 604bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski for (auto &sparse_mem_binding : mem_binding->sparse_bindings) { 605f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis skip |= ClearMemoryObjectBinding(dev_data, handle, type, sparse_mem_binding.mem); 6065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 609f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis return skip; 6105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 6115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 612888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis// For given mem object, verify that it is not null or UNBOUND, if it is, report error. Return skip value. 613888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlisbool VerifyBoundMemoryIsValid(const layer_data *dev_data, VkDeviceMemory mem, uint64_t handle, const char *api_name, 61435ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis const char *type_name, UNIQUE_VALIDATION_ERROR_CODE error_code) { 615888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis bool result = false; 616888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis if (VK_NULL_HANDLE == mem) { 617888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis result = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, handle, 618cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, error_code, "MEM", "%s: Vk%s object 0x%" PRIxLEAST64 619cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " used with no memory bound. Memory should be bound by calling " 620cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkBind%sMemory(). %s", 62135ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis api_name, type_name, handle, type_name, validation_error_map[error_code]); 622888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis } else if (MEMORY_UNBOUND == mem) { 623888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis result = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, handle, 624cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, error_code, "MEM", "%s: Vk%s object 0x%" PRIxLEAST64 625cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " used with no memory bound and previously bound memory was freed. " 626cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Memory must not be freed prior to this operation. %s", 62735ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis api_name, type_name, handle, validation_error_map[error_code]); 628888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis } 629888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis return result; 630888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis} 631888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis 632b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski// Check to see if memory was ever bound to this image 63335ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlisbool ValidateMemoryIsBoundToImage(const layer_data *dev_data, const IMAGE_STATE *image_state, const char *api_name, 63435ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis UNIQUE_VALIDATION_ERROR_CODE error_code) { 635b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski bool result = false; 6361facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis if (0 == (static_cast<uint32_t>(image_state->createInfo.flags) & VK_IMAGE_CREATE_SPARSE_BINDING_BIT)) { 63735ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis result = VerifyBoundMemoryIsValid(dev_data, image_state->binding.mem, 63835ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis reinterpret_cast<const uint64_t &>(image_state->image), api_name, "Image", error_code); 639b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski } 640b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski return result; 641b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski} 642b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski 643b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski// Check to see if memory was bound to this buffer 64435ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlisbool ValidateMemoryIsBoundToBuffer(const layer_data *dev_data, const BUFFER_STATE *buffer_state, const char *api_name, 64535ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis UNIQUE_VALIDATION_ERROR_CODE error_code) { 646b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski bool result = false; 6475cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis if (0 == (static_cast<uint32_t>(buffer_state->createInfo.flags) & VK_BUFFER_CREATE_SPARSE_BINDING_BIT)) { 6485cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis result = VerifyBoundMemoryIsValid(dev_data, buffer_state->binding.mem, 64935ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis reinterpret_cast<const uint64_t &>(buffer_state->buffer), api_name, "Buffer", error_code); 650b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski } 651b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski return result; 652b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski} 653b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski 6543a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// SetMemBinding is used to establish immutable, non-sparse binding between a single image/buffer object and memory object. 6553a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// Corresponding valid usage checks are in ValidateSetMemBinding(). 6567a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinskistatic void SetMemBinding(layer_data *dev_data, VkDeviceMemory mem, uint64_t handle, VulkanObjectType type, const char *apiName) { 657c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton if (mem != VK_NULL_HANDLE) { 658c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton BINDABLE *mem_binding = GetObjectMemBinding(dev_data, handle, type); 659c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton assert(mem_binding); 660c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton DEVICE_MEM_INFO *mem_info = GetMemObjInfo(dev_data, mem); 661c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton if (mem_info) { 662c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton mem_info->obj_bindings.insert({handle, type}); 663c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton // For image objects, make sure default memory state is correctly set 664c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton // TODO : What's the best/correct way to handle this? 6657a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski if (kVulkanObjectTypeImage == type) { 666c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton auto const image_state = GetImageState(dev_data, VkImage(handle)); 667c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton if (image_state) { 668c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton VkImageCreateInfo ici = image_state->createInfo; 669c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton if (ici.usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) { 670c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton // TODO:: More memory state transition stuff. 671c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton } 672c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton } 673c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton } 674c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton mem_binding->binding.mem = mem; 675c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton } 676c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton } 677c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton} 6783a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton 6793a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// Valid usage checks for a call to SetMemBinding(). 6803a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// For NULL mem case, output warning 6813a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// Make sure given object is in global object map 6823a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// IF a previous binding existed, output validation error 6833a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// Otherwise, add reference from objectInfo to memoryInfo 6843a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// Add reference off of objInfo 6853a6c2a8f5135475de5be6de7675ffd9dd27b30d3Cort Stratton// TODO: We may need to refactor or pass in multiple valid usage statements to handle multiple valid usage conditions. 6867a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinskistatic bool ValidateSetMemBinding(layer_data *dev_data, VkDeviceMemory mem, uint64_t handle, VulkanObjectType type, 687c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton const char *apiName) { 6883251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 689f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis // It's an error to bind an object to NULL memory 690d3876b4ff7c293a14f73fe3622513d1fa91bf2d0Jeremy Hayes if (mem != VK_NULL_HANDLE) { 691f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis BINDABLE *mem_binding = GetObjectMemBinding(dev_data, handle, type); 692888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis assert(mem_binding); 69310ffe2d353eaff714ed92a2835af77d8b5042d31Cort if (mem_binding->sparse) { 69410ffe2d353eaff714ed92a2835af77d8b5042d31Cort UNIQUE_VALIDATION_ERROR_CODE error_code = VALIDATION_ERROR_00804; 69510ffe2d353eaff714ed92a2835af77d8b5042d31Cort const char *handle_type = "IMAGE"; 69674300755ed9ec780d6073af71e47f201217008d6Cort Stratton if (strcmp(apiName, "vkBindBufferMemory()") == 0) { 69710ffe2d353eaff714ed92a2835af77d8b5042d31Cort error_code = VALIDATION_ERROR_00792; 69810ffe2d353eaff714ed92a2835af77d8b5042d31Cort handle_type = "BUFFER"; 69910ffe2d353eaff714ed92a2835af77d8b5042d31Cort } else { 70074300755ed9ec780d6073af71e47f201217008d6Cort Stratton assert(strcmp(apiName, "vkBindImageMemory()") == 0); 70110ffe2d353eaff714ed92a2835af77d8b5042d31Cort } 7023251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 7033251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t &>(mem), __LINE__, error_code, "MEM", 7043251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "In %s, attempting to bind memory (0x%" PRIxLEAST64 ") to object (0x%" PRIxLEAST64 7053251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski ") which was created with sparse memory flags (VK_%s_CREATE_SPARSE_*_BIT). %s", 7063251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski apiName, reinterpret_cast<uint64_t &>(mem), handle, handle_type, validation_error_map[error_code]); 70710ffe2d353eaff714ed92a2835af77d8b5042d31Cort } 7089a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *mem_info = GetMemObjInfo(dev_data, mem); 709888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis if (mem_info) { 7109a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *prev_binding = GetMemObjInfo(dev_data, mem_binding->binding.mem); 711888cae09036ec622d6014e18efbda55e6226cf22Tobin Ehlis if (prev_binding) { 71298c2a17e1a549df84f4239f619bc0955f632cb43Cort UNIQUE_VALIDATION_ERROR_CODE error_code = VALIDATION_ERROR_00803; 71374300755ed9ec780d6073af71e47f201217008d6Cort Stratton if (strcmp(apiName, "vkBindBufferMemory()") == 0) { 71498c2a17e1a549df84f4239f619bc0955f632cb43Cort error_code = VALIDATION_ERROR_00791; 71598c2a17e1a549df84f4239f619bc0955f632cb43Cort } else { 71674300755ed9ec780d6073af71e47f201217008d6Cort Stratton assert(strcmp(apiName, "vkBindImageMemory()") == 0); 71798c2a17e1a549df84f4239f619bc0955f632cb43Cort } 7183251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 7193251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t &>(mem), __LINE__, error_code, "MEM", 7203251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "In %s, attempting to bind memory (0x%" PRIxLEAST64 ") to object (0x%" PRIxLEAST64 7213251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski ") which has already been bound to mem object 0x%" PRIxLEAST64 ". %s", 7223251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski apiName, reinterpret_cast<uint64_t &>(mem), handle, reinterpret_cast<uint64_t &>(prev_binding->mem), 7233251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski validation_error_map[error_code]); 724f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis } else if (mem_binding->binding.mem == MEMORY_UNBOUND) { 7253251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 7263251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t &>(mem), __LINE__, MEMTRACK_REBIND_OBJECT, "MEM", 7273251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "In %s, attempting to bind memory (0x%" PRIxLEAST64 ") to object (0x%" PRIxLEAST64 7283251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski ") which was previous bound to memory that has since been freed. Memory bindings are immutable in " 7293251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Vulkan so this attempt to bind to new memory is not allowed.", 7303251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski apiName, reinterpret_cast<uint64_t &>(mem), handle); 7315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7343251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 7355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 7365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// For NULL mem case, clear any previous binding Else... 7385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Make sure given object is in its object map 7395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// IF a previous binding existed, update binding 7405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Add reference from objectInfo to memoryInfo 7415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Add reference off of object's binding info 7420a1ce3dfd81c9f4efbe46f5ba5ddaea70bc4aa61Chris Forbes// Return VK_TRUE if addition is successful, VK_FALSE otherwise 743ece0e981ee4a5ad2572d146a89fc64d699d79f36Chris Forbesstatic bool SetSparseMemBinding(layer_data *dev_data, MEM_BINDING binding, uint64_t handle, VulkanObjectType type) { 7443251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = VK_FALSE; 7455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Handle NULL case separately, just clear previous binding & decrement reference 746f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis if (binding.mem == VK_NULL_HANDLE) { 747f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis // TODO : This should cause the range of the resource to be unbound according to spec 7485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 749f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis BINDABLE *mem_binding = GetObjectMemBinding(dev_data, handle, type); 750f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis assert(mem_binding); 751f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis assert(mem_binding->sparse); 7529a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *mem_info = GetMemObjInfo(dev_data, binding.mem); 753f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis if (mem_info) { 754f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis mem_info->obj_bindings.insert({handle, type}); 7552e415b757c1e43fda35311aad026af8d5c96681cTobin Ehlis // Need to set mem binding for this object 756f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis mem_binding->sparse_bindings.insert(binding); 7575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7593251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 760caf05e0db4959ae196ab34b024f352d9c0326870Tobin Ehlis} 761caf05e0db4959ae196ab34b024f352d9c0326870Tobin Ehlis 7625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// SPIRV utility functions 7635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic void build_def_index(shader_module *module) { 7645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto insn : *module) { 7655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis switch (insn.opcode()) { 766cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Types 767cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeVoid: 768cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeBool: 769cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeInt: 770cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeFloat: 771cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeVector: 772cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeMatrix: 773cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeImage: 774cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeSampler: 775cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeSampledImage: 776cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeArray: 777cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeRuntimeArray: 778cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeStruct: 779cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeOpaque: 780cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypePointer: 781cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeFunction: 782cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeEvent: 783cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeDeviceEvent: 784cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeReserveId: 785cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeQueue: 786cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypePipe: 787cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski module->def_index[insn.word(1)] = insn.offset(); 788cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 7895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 790cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Fixed constants 791cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpConstantTrue: 792cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpConstantFalse: 793cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpConstant: 794cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpConstantComposite: 795cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpConstantSampler: 796cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpConstantNull: 797cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski module->def_index[insn.word(2)] = insn.offset(); 798cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 7995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 800cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Specialization constants 801cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpSpecConstantTrue: 802cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpSpecConstantFalse: 803cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpSpecConstant: 804cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpSpecConstantComposite: 805cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpSpecConstantOp: 806cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski module->def_index[insn.word(2)] = insn.offset(); 807cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 8085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 809cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Variables 810cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpVariable: 811cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski module->def_index[insn.word(2)] = insn.offset(); 812cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 8135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 814cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Functions 815cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpFunction: 816cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski module->def_index[insn.word(2)] = insn.offset(); 817cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 8185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 819cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 820cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // We don't care about any other defs for now. 821cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 8225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 8255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic spirv_inst_iter find_entrypoint(shader_module *src, char const *name, VkShaderStageFlagBits stageBits) { 8275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto insn : *src) { 8285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.opcode() == spv::OpEntryPoint) { 8295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto entrypointName = (char const *)&insn.word(3); 8305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto entrypointStageBits = 1u << insn.word(1); 8315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!strcmp(entrypointName, name) && (entrypointStageBits & stageBits)) { 8335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return insn; 8345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return src->end(); 8395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 8405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic char const *storage_class_name(unsigned sc) { 8425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis switch (sc) { 843cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassInput: 844cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "input"; 845cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassOutput: 846cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "output"; 847cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassUniformConstant: 848cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "const uniform"; 849cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassUniform: 850cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "uniform"; 851cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassWorkgroup: 852cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "workgroup local"; 853cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassCrossWorkgroup: 854cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "workgroup global"; 855cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassPrivate: 856cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "private global"; 857cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassFunction: 858cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "function"; 859cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassGeneric: 860cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "generic"; 861cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassAtomicCounter: 862cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "atomic counter"; 863cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassImage: 864cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "image"; 865cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::StorageClassPushConstant: 866cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "push constant"; 867cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 868cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return "unknown"; 8695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 8715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 87225002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// Get the value of an integral constant 8735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisunsigned get_constant_value(shader_module const *src, unsigned id) { 8745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto value = src->get_def(id); 8755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(value != src->end()); 8765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (value.opcode() != spv::OpConstant) { 87825002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // TODO: Either ensure that the specialization transform is already performed on a module we're 87925002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // considering here, OR -- specialize on the fly now. 8805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return 1; 8815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return value.word(3); 8845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 8855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8869ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbesstatic void describe_type_inner(std::ostringstream &ss, shader_module const *src, unsigned type) { 8875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto insn = src->get_def(type); 8885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(insn != src->end()); 8895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis switch (insn.opcode()) { 891cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeBool: 892cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << "bool"; 893cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 894cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeInt: 895cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << (insn.word(3) ? 's' : 'u') << "int" << insn.word(2); 896cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 897cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeFloat: 898cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << "float" << insn.word(2); 899cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 900cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeVector: 901cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << "vec" << insn.word(3) << " of "; 902cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski describe_type_inner(ss, src, insn.word(2)); 903cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 904cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeMatrix: 905cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << "mat" << insn.word(3) << " of "; 906cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski describe_type_inner(ss, src, insn.word(2)); 907cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 908cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeArray: 909cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << "arr[" << get_constant_value(src, insn.word(3)) << "] of "; 910cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski describe_type_inner(ss, src, insn.word(2)); 911cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 912cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypePointer: 913cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << "ptr to " << storage_class_name(insn.word(2)) << " "; 914cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski describe_type_inner(ss, src, insn.word(3)); 915cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 916cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeStruct: { 917cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << "struct of ("; 918cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski for (unsigned i = 2; i < insn.len(); i++) { 919cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski describe_type_inner(ss, src, insn.word(i)); 920cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (i == insn.len() - 1) { 921cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << ")"; 922cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else { 923cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << ", "; 924cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 9259ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes } 926cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 9275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 928cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeSampler: 929cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << "sampler"; 930cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 931cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeSampledImage: 932cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << "sampler+"; 933cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski describe_type_inner(ss, src, insn.word(2)); 934cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 935cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeImage: 936cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << "image(dim=" << insn.word(3) << ", sampled=" << insn.word(7) << ")"; 937cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 938cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 939cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ss << "oddtype"; 940cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 9415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 9435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9449ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbesstatic std::string describe_type(shader_module const *src, unsigned type) { 9459ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes std::ostringstream ss; 9469ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes describe_type_inner(ss, src, type); 9479ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes return ss.str(); 9489ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes} 9499ccb7b1342fd1a901f1ae0d202721a50d2c227f9Chris Forbes 950bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic bool is_narrow_numeric_type(spirv_inst_iter type) { 951cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (type.opcode() != spv::OpTypeInt && type.opcode() != spv::OpTypeFloat) return false; 95237576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes return type.word(2) < 64; 95337576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes} 95437576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes 955bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic bool types_match(shader_module const *a, shader_module const *b, unsigned a_type, unsigned b_type, bool a_arrayed, 956bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski bool b_arrayed, bool relaxed) { 95725002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Walk two type trees together, and complain about differences 9585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto a_insn = a->get_def(a_type); 9595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto b_insn = b->get_def(b_type); 9605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(a_insn != a->end()); 9615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(b_insn != b->end()); 9625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9637c755c8aca6857046df9516d8336416165969cb9Chris Forbes if (a_arrayed && a_insn.opcode() == spv::OpTypeArray) { 96437576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes return types_match(a, b, a_insn.word(2), b_type, false, b_arrayed, relaxed); 9657c755c8aca6857046df9516d8336416165969cb9Chris Forbes } 9667c755c8aca6857046df9516d8336416165969cb9Chris Forbes 9675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (b_arrayed && b_insn.opcode() == spv::OpTypeArray) { 96825002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // We probably just found the extra level of arrayness in b_type: compare the type inside it to a_type 96937576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes return types_match(a, b, a_type, b_insn.word(2), a_arrayed, false, relaxed); 97037576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes } 97137576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes 97237576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes if (a_insn.opcode() == spv::OpTypeVector && relaxed && is_narrow_numeric_type(b_insn)) { 97337576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes return types_match(a, b, a_insn.word(2), b_type, a_arrayed, b_arrayed, false); 9745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (a_insn.opcode() != b_insn.opcode()) { 9775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 9785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9807c755c8aca6857046df9516d8336416165969cb9Chris Forbes if (a_insn.opcode() == spv::OpTypePointer) { 98125002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Match on pointee type. storage class is expected to differ 98237576f9c5ccc190c53a1c10baf383d77c3c6d476Chris Forbes return types_match(a, b, a_insn.word(3), b_insn.word(3), a_arrayed, b_arrayed, relaxed); 9837c755c8aca6857046df9516d8336416165969cb9Chris Forbes } 9847c755c8aca6857046df9516d8336416165969cb9Chris Forbes 9857c755c8aca6857046df9516d8336416165969cb9Chris Forbes if (a_arrayed || b_arrayed) { 98625002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // If we havent resolved array-of-verts by here, we're not going to. 9877c755c8aca6857046df9516d8336416165969cb9Chris Forbes return false; 9887c755c8aca6857046df9516d8336416165969cb9Chris Forbes } 9897c755c8aca6857046df9516d8336416165969cb9Chris Forbes 9905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis switch (a_insn.opcode()) { 991cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeBool: 992cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return true; 993cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeInt: 994cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Match on width, signedness 995cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return a_insn.word(2) == b_insn.word(2) && a_insn.word(3) == b_insn.word(3); 996cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeFloat: 997cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Match on width 998cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return a_insn.word(2) == b_insn.word(2); 999cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeVector: 1000cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Match on element type, count. 1001cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!types_match(a, b, a_insn.word(2), b_insn.word(2), a_arrayed, b_arrayed, false)) return false; 1002cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (relaxed && is_narrow_numeric_type(a->get_def(a_insn.word(2)))) { 1003cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return a_insn.word(3) >= b_insn.word(3); 1004cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else { 1005cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return a_insn.word(3) == b_insn.word(3); 10065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 1007cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeMatrix: 1008cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Match on element type, count. 1009cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return types_match(a, b, a_insn.word(2), b_insn.word(2), a_arrayed, b_arrayed, false) && 1010cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski a_insn.word(3) == b_insn.word(3); 1011cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeArray: 1012cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Match on element type, count. these all have the same layout. we don't get here if b_arrayed. This differs from 1013cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // vector & matrix types in that the array size is the id of a constant instruction, * not a literal within OpTypeArray 1014cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return types_match(a, b, a_insn.word(2), b_insn.word(2), a_arrayed, b_arrayed, false) && 1015cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski get_constant_value(a, a_insn.word(3)) == get_constant_value(b, b_insn.word(3)); 1016cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeStruct: 1017cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Match on all element types 1018cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski { 1019cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (a_insn.len() != b_insn.len()) { 1020cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return false; // Structs cannot match if member counts differ 1021cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 10225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1023cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski for (unsigned i = 2; i < a_insn.len(); i++) { 1024cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!types_match(a, b, a_insn.word(i), b_insn.word(i), a_arrayed, b_arrayed, false)) { 1025cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return false; 1026cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 1027cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 1028cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski 1029cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return true; 1030cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 1031cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 1032cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Remaining types are CLisms, or may not appear in the interfaces we are interested in. Just claim no match. 1033cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return false; 10345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 10355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 10365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10372c81be6aa02b10d9e225329977fa108ceda890a2Chris Forbesstatic unsigned value_or_default(std::unordered_map<unsigned, unsigned> const &map, unsigned id, unsigned def) { 10385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto it = map.find(id); 10395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (it == map.end()) 10405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return def; 10415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis else 10425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return it->second; 10435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 10445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic unsigned get_locations_consumed_by_type(shader_module const *src, unsigned type, bool strip_array_level) { 10465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto insn = src->get_def(type); 10475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(insn != src->end()); 10485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis switch (insn.opcode()) { 1050cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypePointer: 1051cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // See through the ptr -- this is only ever at the toplevel for graphics shaders we're never actually passing 1052cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // pointers around. 1053cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return get_locations_consumed_by_type(src, insn.word(3), strip_array_level); 1054cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeArray: 1055cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (strip_array_level) { 1056cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return get_locations_consumed_by_type(src, insn.word(2), false); 1057cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else { 1058cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return get_constant_value(src, insn.word(3)) * get_locations_consumed_by_type(src, insn.word(2), false); 1059cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 1060cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeMatrix: 1061cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Num locations is the dimension * element size 1062cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return insn.word(3) * get_locations_consumed_by_type(src, insn.word(2), false); 1063cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeVector: { 1064cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski auto scalar_type = src->get_def(insn.word(2)); 1065cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski auto bit_width = 1066cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski (scalar_type.opcode() == spv::OpTypeInt || scalar_type.opcode() == spv::OpTypeFloat) ? scalar_type.word(2) : 32; 1067cc52143fc093e1e62d2dacc4abc3966e04b6f6d6Chris Forbes 1068cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Locations are 128-bit wide; 3- and 4-component vectors of 64 bit types require two. 1069cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return (bit_width * insn.word(3) + 127) / 128; 1070cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 1071cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 1072cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Everything else is just 1. 1073cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return 1; 10745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1075cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // TODO: extend to handle 64bit scalar types, whose vectors may need multiple locations. 10765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 10775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 10785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1079c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbesstatic unsigned get_locations_consumed_by_format(VkFormat format) { 1080c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes switch (format) { 1081cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64G64B64A64_SFLOAT: 1082cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64G64B64A64_SINT: 1083cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64G64B64A64_UINT: 1084cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64G64B64_SFLOAT: 1085cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64G64B64_SINT: 1086cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_FORMAT_R64G64B64_UINT: 1087cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return 2; 1088cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 1089cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return 1; 1090c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes } 1091c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes} 1092c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes 10935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlistypedef std::pair<unsigned, unsigned> location_t; 10945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlistypedef std::pair<unsigned, unsigned> descriptor_slot_t; 10955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstruct interface_var { 10975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t id; 10985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t type_id; 10995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t offset; 1100b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes bool is_patch; 1101fff9393206f66a154438e16fa0562c989f425498Chris Forbes bool is_block_member; 1102b0436668e6594b8528e96de7bed208399fb2431dChris Forbes bool is_relaxed_precision; 110325002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // TODO: collect the name, too? Isn't required to be present. 11045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}; 11055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1106031261d21af8907953dd763398ce9a23e65b8749Chris Forbesstruct shader_stage_attributes { 1107031261d21af8907953dd763398ce9a23e65b8749Chris Forbes char const *const name; 1108031261d21af8907953dd763398ce9a23e65b8749Chris Forbes bool arrayed_input; 1109031261d21af8907953dd763398ce9a23e65b8749Chris Forbes bool arrayed_output; 1110031261d21af8907953dd763398ce9a23e65b8749Chris Forbes}; 1111031261d21af8907953dd763398ce9a23e65b8749Chris Forbes 1112031261d21af8907953dd763398ce9a23e65b8749Chris Forbesstatic shader_stage_attributes shader_stage_attribs[] = { 1113bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vertex shader", false, false}, {"tessellation control shader", true, true}, {"tessellation evaluation shader", true, false}, 1114bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"geometry shader", true, false}, {"fragment shader", false, false}, 1115031261d21af8907953dd763398ce9a23e65b8749Chris Forbes}; 1116031261d21af8907953dd763398ce9a23e65b8749Chris Forbes 11175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic spirv_inst_iter get_struct_type(shader_module const *src, spirv_inst_iter def, bool is_array_of_verts) { 11185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis while (true) { 11195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (def.opcode() == spv::OpTypePointer) { 11205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis def = src->get_def(def.word(3)); 11215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (def.opcode() == spv::OpTypeArray && is_array_of_verts) { 11225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis def = src->get_def(def.word(2)); 11235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis is_array_of_verts = false; 11245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (def.opcode() == spv::OpTypeStruct) { 11255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return def; 11265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 11275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return src->end(); 11285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 11295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 11305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 11315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1132bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic void collect_interface_block_members(shader_module const *src, std::map<location_t, interface_var> *out, 11335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_map<unsigned, unsigned> const &blocks, bool is_array_of_verts, 1134b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes uint32_t id, uint32_t type_id, bool is_patch) { 113525002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Walk down the type_id presented, trying to determine whether it's actually an interface block. 1136031261d21af8907953dd763398ce9a23e65b8749Chris Forbes auto type = get_struct_type(src, src->get_def(type_id), is_array_of_verts && !is_patch); 11375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (type == src->end() || blocks.find(type.word(1)) == blocks.end()) { 113825002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // This isn't an interface block. 11395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return; 11405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 11415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 11425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_map<unsigned, unsigned> member_components; 11435b9f2047984d6ca10d89a35ba8a2ebe0fa6bff69Chris Forbes std::unordered_map<unsigned, unsigned> member_relaxed_precision; 11445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 114525002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Walk all the OpMemberDecorate for type's result id -- first pass, collect components. 11465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto insn : *src) { 11475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.opcode() == spv::OpMemberDecorate && insn.word(1) == type.word(1)) { 11485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned member_index = insn.word(2); 11495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 11505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.word(3) == spv::DecorationComponent) { 11515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned component = insn.word(4); 11525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis member_components[member_index] = component; 11535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 11545b9f2047984d6ca10d89a35ba8a2ebe0fa6bff69Chris Forbes 11555b9f2047984d6ca10d89a35ba8a2ebe0fa6bff69Chris Forbes if (insn.word(3) == spv::DecorationRelaxedPrecision) { 11565b9f2047984d6ca10d89a35ba8a2ebe0fa6bff69Chris Forbes member_relaxed_precision[member_index] = 1; 11575b9f2047984d6ca10d89a35ba8a2ebe0fa6bff69Chris Forbes } 11585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 11595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 11605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 116125002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Second pass -- produce the output, from Location decorations 11625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto insn : *src) { 11635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.opcode() == spv::OpMemberDecorate && insn.word(1) == type.word(1)) { 11645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned member_index = insn.word(2); 11655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned member_type_id = type.word(2 + member_index); 11665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 11675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.word(3) == spv::DecorationLocation) { 11685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned location = insn.word(4); 11695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned num_locations = get_locations_consumed_by_type(src, member_type_id, false); 11705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto component_it = member_components.find(member_index); 11715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned component = component_it == member_components.end() ? 0 : component_it->second; 11725b9f2047984d6ca10d89a35ba8a2ebe0fa6bff69Chris Forbes bool is_relaxed_precision = member_relaxed_precision.find(member_index) != member_relaxed_precision.end(); 11735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 11745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (unsigned int offset = 0; offset < num_locations; offset++) { 1175b0436668e6594b8528e96de7bed208399fb2431dChris Forbes interface_var v = {}; 11765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis v.id = id; 117725002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // TODO: member index in interface_var too? 11785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis v.type_id = member_type_id; 11795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis v.offset = offset; 1180b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes v.is_patch = is_patch; 1181fff9393206f66a154438e16fa0562c989f425498Chris Forbes v.is_block_member = true; 11825b9f2047984d6ca10d89a35ba8a2ebe0fa6bff69Chris Forbes v.is_relaxed_precision = is_relaxed_precision; 11833a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes (*out)[std::make_pair(location + offset, component)] = v; 11845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 11855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 11865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 11875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 11885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 11895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1190bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic std::map<location_t, interface_var> collect_interface_by_location(shader_module const *src, spirv_inst_iter entrypoint, 1191bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski spv::StorageClass sinterface, bool is_array_of_verts) { 11925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_map<unsigned, unsigned> var_locations; 11935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_map<unsigned, unsigned> var_builtins; 11945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_map<unsigned, unsigned> var_components; 11955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_map<unsigned, unsigned> blocks; 1196b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes std::unordered_map<unsigned, unsigned> var_patch; 1197b0436668e6594b8528e96de7bed208399fb2431dChris Forbes std::unordered_map<unsigned, unsigned> var_relaxed_precision; 11985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 11995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto insn : *src) { 120025002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // We consider two interface models: SSO rendezvous-by-location, and builtins. Complain about anything that 120125002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // fits neither model. 12025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.opcode() == spv::OpDecorate) { 12035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.word(2) == spv::DecorationLocation) { 12045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis var_locations[insn.word(1)] = insn.word(3); 12055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 12065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 12075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.word(2) == spv::DecorationBuiltIn) { 12085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis var_builtins[insn.word(1)] = insn.word(3); 12095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 12105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 12115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.word(2) == spv::DecorationComponent) { 12125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis var_components[insn.word(1)] = insn.word(3); 12135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 12145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 12155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.word(2) == spv::DecorationBlock) { 12165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis blocks[insn.word(1)] = 1; 12175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 1218b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes 1219b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes if (insn.word(2) == spv::DecorationPatch) { 1220b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes var_patch[insn.word(1)] = 1; 1221b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes } 1222b0436668e6594b8528e96de7bed208399fb2431dChris Forbes 1223b0436668e6594b8528e96de7bed208399fb2431dChris Forbes if (insn.word(2) == spv::DecorationRelaxedPrecision) { 1224b0436668e6594b8528e96de7bed208399fb2431dChris Forbes var_relaxed_precision[insn.word(1)] = 1; 1225b0436668e6594b8528e96de7bed208399fb2431dChris Forbes } 12265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 12275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 12285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 122925002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // TODO: handle grouped decorations 123025002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // TODO: handle index=1 dual source outputs from FS -- two vars will have the same location, and we DON'T want to clobber. 12315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 123225002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Find the end of the entrypoint's name string. additional zero bytes follow the actual null terminator, to fill out the 123325002b75574f762c62b1a00a595bab04ebb25452Mark 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. 1234c15b801a6e1a5dd5eed09e689aecdde7c4a90a5bMichael Mc Donnell uint32_t word = 3; 12355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis while (entrypoint.word(word) & 0xff000000u) { 12365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis ++word; 12375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 12385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis ++word; 12395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 12403a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes std::map<location_t, interface_var> out; 12413a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes 12425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (; word < entrypoint.len(); word++) { 12435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto insn = src->get_def(entrypoint.word(word)); 12445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(insn != src->end()); 12455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(insn.opcode() == spv::OpVariable); 12465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 12471d5109d5e0dcc530b27e632e73e1be5e12a28dcdJamie Madill if (insn.word(3) == static_cast<uint32_t>(sinterface)) { 12485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned id = insn.word(2); 12495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned type = insn.word(1); 12505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 12515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis int location = value_or_default(var_locations, id, -1); 12525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis int builtin = value_or_default(var_builtins, id, -1); 1253cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski unsigned component = value_or_default(var_components, id, 0); // Unspecified is OK, is 0 1254b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes bool is_patch = var_patch.find(id) != var_patch.end(); 1255b0436668e6594b8528e96de7bed208399fb2431dChris Forbes bool is_relaxed_precision = var_relaxed_precision.find(id) != var_relaxed_precision.end(); 12565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 125725002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // All variables and interface block members in the Input or Output storage classes must be decorated with either 125825002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // a builtin or an explicit location. 125925002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // 126025002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // TODO: integrate the interface block support here. For now, don't complain -- a valid SPIRV module will only hit 126125002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // this path for the interface block case, as the individual members of the type are decorated, rather than 126225002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // variable declarations. 12635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 12645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (location != -1) { 126525002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // A user-defined interface variable, with a location. Where a variable occupied multiple locations, emit 126625002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // one result for each. 12677c755c8aca6857046df9516d8336416165969cb9Chris Forbes unsigned num_locations = get_locations_consumed_by_type(src, type, is_array_of_verts && !is_patch); 12685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (unsigned int offset = 0; offset < num_locations; offset++) { 1269b0436668e6594b8528e96de7bed208399fb2431dChris Forbes interface_var v = {}; 12705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis v.id = id; 12715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis v.type_id = type; 12725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis v.offset = offset; 1273b934cb26db50b965da46ca3e3f006d5a93478f71Chris Forbes v.is_patch = is_patch; 1274b0436668e6594b8528e96de7bed208399fb2431dChris Forbes v.is_relaxed_precision = is_relaxed_precision; 12755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis out[std::make_pair(location + offset, component)] = v; 12765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 12775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (builtin == -1) { 127825002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // An interface block instance 12793a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes collect_interface_block_members(src, &out, blocks, is_array_of_verts, id, type, is_patch); 12805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 12815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 12825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 12833a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes 12843a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes return out; 12855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 12865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 128712b7fc342b53fbdd399aae4a85959e37685936acChris Forbesstatic vector<std::pair<uint32_t, interface_var>> collect_interface_by_input_attachment_index( 128812b7fc342b53fbdd399aae4a85959e37685936acChris Forbes shader_module const *src, std::unordered_set<uint32_t> const &accessible_ids) { 12893a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes std::vector<std::pair<uint32_t, interface_var>> out; 1290745d49409296f060402b57950384caadb636a2b2Chris Forbes 1291745d49409296f060402b57950384caadb636a2b2Chris Forbes for (auto insn : *src) { 1292745d49409296f060402b57950384caadb636a2b2Chris Forbes if (insn.opcode() == spv::OpDecorate) { 1293745d49409296f060402b57950384caadb636a2b2Chris Forbes if (insn.word(2) == spv::DecorationInputAttachmentIndex) { 1294745d49409296f060402b57950384caadb636a2b2Chris Forbes auto attachment_index = insn.word(3); 1295745d49409296f060402b57950384caadb636a2b2Chris Forbes auto id = insn.word(1); 1296745d49409296f060402b57950384caadb636a2b2Chris Forbes 1297745d49409296f060402b57950384caadb636a2b2Chris Forbes if (accessible_ids.count(id)) { 1298745d49409296f060402b57950384caadb636a2b2Chris Forbes auto def = src->get_def(id); 1299745d49409296f060402b57950384caadb636a2b2Chris Forbes assert(def != src->end()); 1300745d49409296f060402b57950384caadb636a2b2Chris Forbes 1301745d49409296f060402b57950384caadb636a2b2Chris Forbes if (def.opcode() == spv::OpVariable && insn.word(3) == spv::StorageClassUniformConstant) { 1302e0cc9b3441a24e4fbd2b4e0a9d163dab2140264aChris Forbes auto num_locations = get_locations_consumed_by_type(src, def.word(1), false); 1303e0cc9b3441a24e4fbd2b4e0a9d163dab2140264aChris Forbes for (unsigned int offset = 0; offset < num_locations; offset++) { 1304b0436668e6594b8528e96de7bed208399fb2431dChris Forbes interface_var v = {}; 1305e0cc9b3441a24e4fbd2b4e0a9d163dab2140264aChris Forbes v.id = id; 1306e0cc9b3441a24e4fbd2b4e0a9d163dab2140264aChris Forbes v.type_id = def.word(1); 1307e0cc9b3441a24e4fbd2b4e0a9d163dab2140264aChris Forbes v.offset = offset; 1308e0cc9b3441a24e4fbd2b4e0a9d163dab2140264aChris Forbes out.emplace_back(attachment_index + offset, v); 1309e0cc9b3441a24e4fbd2b4e0a9d163dab2140264aChris Forbes } 1310745d49409296f060402b57950384caadb636a2b2Chris Forbes } 1311745d49409296f060402b57950384caadb636a2b2Chris Forbes } 1312745d49409296f060402b57950384caadb636a2b2Chris Forbes } 1313745d49409296f060402b57950384caadb636a2b2Chris Forbes } 1314745d49409296f060402b57950384caadb636a2b2Chris Forbes } 13153a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes 13163a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes return out; 1317745d49409296f060402b57950384caadb636a2b2Chris Forbes} 1318745d49409296f060402b57950384caadb636a2b2Chris Forbes 1319cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskistatic std::vector<std::pair<descriptor_slot_t, interface_var>> collect_interface_by_descriptor_slot( 1320cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski debug_report_data *report_data, shader_module const *src, std::unordered_set<uint32_t> const &accessible_ids) { 13215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_map<unsigned, unsigned> var_sets; 13225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_map<unsigned, unsigned> var_bindings; 13235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 13245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto insn : *src) { 132525002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // All variables in the Uniform or UniformConstant storage classes are required to be decorated with both 132625002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // DecorationDescriptorSet and DecorationBinding. 13275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.opcode() == spv::OpDecorate) { 13285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.word(2) == spv::DecorationDescriptorSet) { 13295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis var_sets[insn.word(1)] = insn.word(3); 13305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 13325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.word(2) == spv::DecorationBinding) { 13335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis var_bindings[insn.word(1)] = insn.word(3); 13345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 13383a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes std::vector<std::pair<descriptor_slot_t, interface_var>> out; 13393a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes 13405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto id : accessible_ids) { 13415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto insn = src->get_def(id); 13425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(insn != src->end()); 13435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 13445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.opcode() == spv::OpVariable && 13455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (insn.word(3) == spv::StorageClassUniform || insn.word(3) == spv::StorageClassUniformConstant)) { 13465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned set = value_or_default(var_sets, insn.word(2), 0); 13475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned binding = value_or_default(var_bindings, insn.word(2), 0); 13485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1349b0436668e6594b8528e96de7bed208399fb2431dChris Forbes interface_var v = {}; 13505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis v.id = insn.word(2); 13515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis v.type_id = insn.word(1); 1352cefd4dd8e03c5dae11a05d04a03cb856190358e0Chris Forbes out.emplace_back(std::make_pair(set, binding), v); 13535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 13553a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes 13563a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes return out; 13575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 13585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1359edef66e03ed509994449d598f4fadea1a487d41bChris Forbesstatic bool validate_interface_between_stages(debug_report_data *report_data, shader_module const *producer, 1360031261d21af8907953dd763398ce9a23e65b8749Chris Forbes spirv_inst_iter producer_entrypoint, shader_stage_attributes const *producer_stage, 13615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis shader_module const *consumer, spirv_inst_iter consumer_entrypoint, 1362031261d21af8907953dd763398ce9a23e65b8749Chris Forbes shader_stage_attributes const *consumer_stage) { 13631b52022446fb65466dfcee491393670ac12aaa33Chris Forbes bool skip = false; 13645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1365bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto outputs = 1366bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski collect_interface_by_location(producer, producer_entrypoint, spv::StorageClassOutput, producer_stage->arrayed_output); 1367bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto inputs = 1368bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski collect_interface_by_location(consumer, consumer_entrypoint, spv::StorageClassInput, consumer_stage->arrayed_input); 13695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 13705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto a_it = outputs.begin(); 13715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto b_it = inputs.begin(); 13725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 137325002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Maps sorted by key (location); walk them together to find mismatches 13745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis while ((outputs.size() > 0 && a_it != outputs.end()) || (inputs.size() && b_it != inputs.end())) { 13755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool a_at_end = outputs.size() == 0 || a_it == outputs.end(); 13765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool b_at_end = inputs.size() == 0 || b_it == inputs.end(); 13775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto a_first = a_at_end ? std::make_pair(0u, 0u) : a_it->first; 13785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto b_first = b_at_end ? std::make_pair(0u, 0u) : b_it->first; 13795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 13805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (b_at_end || ((!a_at_end) && (a_first < b_first))) { 13811b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= log_msg(report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 13821b52022446fb65466dfcee491393670ac12aaa33Chris Forbes __LINE__, SHADER_CHECKER_OUTPUT_NOT_CONSUMED, "SC", 13831b52022446fb65466dfcee491393670ac12aaa33Chris Forbes "%s writes to output location %u.%u which is not consumed by %s", producer_stage->name, a_first.first, 13841b52022446fb65466dfcee491393670ac12aaa33Chris Forbes a_first.second, consumer_stage->name); 13855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis a_it++; 13865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (a_at_end || a_first > b_first) { 13871b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 13881b52022446fb65466dfcee491393670ac12aaa33Chris Forbes SHADER_CHECKER_INPUT_NOT_PRODUCED, "SC", "%s consumes input location %u.%u which is not written by %s", 13891b52022446fb65466dfcee491393670ac12aaa33Chris Forbes consumer_stage->name, b_first.first, b_first.second, producer_stage->name); 13905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis b_it++; 13915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 1392fff9393206f66a154438e16fa0562c989f425498Chris Forbes // subtleties of arrayed interfaces: 1393fff9393206f66a154438e16fa0562c989f425498Chris Forbes // - if is_patch, then the member is not arrayed, even though the interface may be. 1394fff9393206f66a154438e16fa0562c989f425498Chris Forbes // - if is_block_member, then the extra array level of an arrayed interface is not 1395fff9393206f66a154438e16fa0562c989f425498Chris Forbes // expressed in the member type -- it's expressed in the block type. 13960f44c68c2575ba2fc83d8c8f2f5ea09548f40686Chris Forbes if (!types_match(producer, consumer, a_it->second.type_id, b_it->second.type_id, 1397fff9393206f66a154438e16fa0562c989f425498Chris Forbes producer_stage->arrayed_output && !a_it->second.is_patch && !a_it->second.is_block_member, 1398bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski consumer_stage->arrayed_input && !b_it->second.is_patch && !b_it->second.is_block_member, true)) { 13991b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 14001b52022446fb65466dfcee491393670ac12aaa33Chris Forbes SHADER_CHECKER_INTERFACE_TYPE_MISMATCH, "SC", "Type mismatch on location %u.%u: '%s' vs '%s'", 14011b52022446fb65466dfcee491393670ac12aaa33Chris Forbes a_first.first, a_first.second, describe_type(producer, a_it->second.type_id).c_str(), 14021b52022446fb65466dfcee491393670ac12aaa33Chris Forbes describe_type(consumer, b_it->second.type_id).c_str()); 14035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 14040f44c68c2575ba2fc83d8c8f2f5ea09548f40686Chris Forbes if (a_it->second.is_patch != b_it->second.is_patch) { 14051b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 0, __LINE__, 14061b52022446fb65466dfcee491393670ac12aaa33Chris Forbes SHADER_CHECKER_INTERFACE_TYPE_MISMATCH, "SC", 14071b52022446fb65466dfcee491393670ac12aaa33Chris Forbes "Decoration mismatch on location %u.%u: is per-%s in %s stage but " 14081b52022446fb65466dfcee491393670ac12aaa33Chris Forbes "per-%s in %s stage", 14091b52022446fb65466dfcee491393670ac12aaa33Chris Forbes a_first.first, a_first.second, a_it->second.is_patch ? "patch" : "vertex", producer_stage->name, 14101b52022446fb65466dfcee491393670ac12aaa33Chris Forbes b_it->second.is_patch ? "patch" : "vertex", consumer_stage->name); 14110f44c68c2575ba2fc83d8c8f2f5ea09548f40686Chris Forbes } 141217c6bacf91ac671cb33212071b87b8ea782812f5Chris Forbes if (a_it->second.is_relaxed_precision != b_it->second.is_relaxed_precision) { 14131b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 0, __LINE__, 14141b52022446fb65466dfcee491393670ac12aaa33Chris Forbes SHADER_CHECKER_INTERFACE_TYPE_MISMATCH, "SC", 14151b52022446fb65466dfcee491393670ac12aaa33Chris Forbes "Decoration mismatch on location %u.%u: %s and %s stages differ in precision", a_first.first, 14161b52022446fb65466dfcee491393670ac12aaa33Chris Forbes a_first.second, producer_stage->name, consumer_stage->name); 141717c6bacf91ac671cb33212071b87b8ea782812f5Chris Forbes } 14185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis a_it++; 14195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis b_it++; 14205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 14215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 14225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 14231b52022446fb65466dfcee491393670ac12aaa33Chris Forbes return skip; 14245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 14255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 14265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisenum FORMAT_TYPE { 1427f0fdde7692ffd5175435cc3bf3412b8468054f38Chris Forbes FORMAT_TYPE_FLOAT = 1, // UNORM, SNORM, FLOAT, USCALED, SSCALED, SRGB -- anything we consider float in the shader 1428f0fdde7692ffd5175435cc3bf3412b8468054f38Chris Forbes FORMAT_TYPE_SINT = 2, 1429f0fdde7692ffd5175435cc3bf3412b8468054f38Chris Forbes FORMAT_TYPE_UINT = 4, 14305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis}; 14315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 14325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic unsigned get_format_type(VkFormat fmt) { 143328f7140700a1624f4836243204237c80645e0fb9Chris Forbes if (FormatIsSInt(fmt)) 143428f7140700a1624f4836243204237c80645e0fb9Chris Forbes return FORMAT_TYPE_SINT; 143528f7140700a1624f4836243204237c80645e0fb9Chris Forbes if (FormatIsUInt(fmt)) 143628f7140700a1624f4836243204237c80645e0fb9Chris Forbes return FORMAT_TYPE_UINT; 143728f7140700a1624f4836243204237c80645e0fb9Chris Forbes if (FormatIsDepthAndStencil(fmt)) 143828f7140700a1624f4836243204237c80645e0fb9Chris Forbes return FORMAT_TYPE_FLOAT | FORMAT_TYPE_UINT; 143928f7140700a1624f4836243204237c80645e0fb9Chris Forbes if (fmt == VK_FORMAT_UNDEFINED) 144028f7140700a1624f4836243204237c80645e0fb9Chris Forbes return 0; 144128f7140700a1624f4836243204237c80645e0fb9Chris Forbes // everything else -- UNORM/SNORM/FLOAT/USCALED/SSCALED is all float in the shader. 144228f7140700a1624f4836243204237c80645e0fb9Chris Forbes return FORMAT_TYPE_FLOAT; 14435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 14445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 144525002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// characterizes a SPIR-V type appearing in an interface to a FF stage, for comparison to a VkFormat's characterization above. 14465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic unsigned get_fundamental_type(shader_module const *src, unsigned type) { 14475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto insn = src->get_def(type); 14485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(insn != src->end()); 14495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 14505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis switch (insn.opcode()) { 1451cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeInt: 1452cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return insn.word(3) ? FORMAT_TYPE_SINT : FORMAT_TYPE_UINT; 1453cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeFloat: 1454cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return FORMAT_TYPE_FLOAT; 1455cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeVector: 1456cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return get_fundamental_type(src, insn.word(2)); 1457cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeMatrix: 1458cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return get_fundamental_type(src, insn.word(2)); 1459cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeArray: 1460cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return get_fundamental_type(src, insn.word(2)); 1461cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypePointer: 1462cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return get_fundamental_type(src, insn.word(3)); 1463cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeImage: 1464cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return get_fundamental_type(src, insn.word(2)); 1465cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski 1466cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 1467f0fdde7692ffd5175435cc3bf3412b8468054f38Chris Forbes return 0; 14685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 14695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 14705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 14715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic uint32_t get_shader_stage_id(VkShaderStageFlagBits stage) { 14728e88ad80aacad2085e76016e7bb29d243ce7f7b6Chris Forbes uint32_t bit_pos = uint32_t(u_ffs(stage)); 14735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return bit_pos - 1; 14745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 14755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1476edef66e03ed509994449d598f4fadea1a487d41bChris Forbesstatic bool validate_vi_consistency(debug_report_data *report_data, VkPipelineVertexInputStateCreateInfo const *vi) { 147725002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Walk the binding descriptions, which describe the step rate and stride of each vertex buffer. Each binding should 147825002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // be specified only once. 14795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_map<uint32_t, VkVertexInputBindingDescription const *> bindings; 14801b52022446fb65466dfcee491393670ac12aaa33Chris Forbes bool skip = false; 14815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 14825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (unsigned i = 0; i < vi->vertexBindingDescriptionCount; i++) { 14835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto desc = &vi->pVertexBindingDescriptions[i]; 14845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto &binding = bindings[desc->binding]; 14855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (binding) { 14864f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes // TODO: VALIDATION_ERROR_02105 perhaps? 14871b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 1488bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SHADER_CHECKER_INCONSISTENT_VI, "SC", "Duplicate vertex input binding descriptions for binding %d", 14891b52022446fb65466dfcee491393670ac12aaa33Chris Forbes desc->binding); 14905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 14915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis binding = desc; 14925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 14935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 14945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 14951b52022446fb65466dfcee491393670ac12aaa33Chris Forbes return skip; 14965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 14975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1498edef66e03ed509994449d598f4fadea1a487d41bChris Forbesstatic bool validate_vi_against_vs_inputs(debug_report_data *report_data, VkPipelineVertexInputStateCreateInfo const *vi, 14995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis shader_module const *vs, spirv_inst_iter entrypoint) { 15001b52022446fb65466dfcee491393670ac12aaa33Chris Forbes bool skip = false; 15015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 15023a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes auto inputs = collect_interface_by_location(vs, entrypoint, spv::StorageClassInput, false); 15035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 150425002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Build index by location 15055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::map<uint32_t, VkVertexInputAttributeDescription const *> attribs; 15065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (vi) { 1507c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes for (unsigned i = 0; i < vi->vertexAttributeDescriptionCount; i++) { 1508c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes auto num_locations = get_locations_consumed_by_format(vi->pVertexAttributeDescriptions[i].format); 1509c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes for (auto j = 0u; j < num_locations; j++) { 1510c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes attribs[vi->pVertexAttributeDescriptions[i].location + j] = &vi->pVertexAttributeDescriptions[i]; 1511c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes } 1512c7255e92ea81e8639dc21388ec2a959bd63319c7Chris Forbes } 15135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 15145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 15155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto it_a = attribs.begin(); 15165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto it_b = inputs.begin(); 15171730e0dd28b3abc660b4e4704cf6d414f7fd4ad6Chris Forbes bool used = false; 15185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 15195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis while ((attribs.size() > 0 && it_a != attribs.end()) || (inputs.size() > 0 && it_b != inputs.end())) { 15205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool a_at_end = attribs.size() == 0 || it_a == attribs.end(); 15215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool b_at_end = inputs.size() == 0 || it_b == inputs.end(); 15225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto a_first = a_at_end ? 0 : it_a->first; 15235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto b_first = b_at_end ? 0 : it_b->first.first; 15245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!a_at_end && (b_at_end || a_first < b_first)) { 15255b9ab1fb8720c30edfbe8dd974e2364425471ad5Mark Lobodzinski if (!used && log_msg(report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 15265b9ab1fb8720c30edfbe8dd974e2364425471ad5Mark Lobodzinski 0, __LINE__, SHADER_CHECKER_OUTPUT_NOT_CONSUMED, "SC", 1527bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "Vertex attribute at location %d not consumed by vertex shader", a_first)) { 15281b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip = true; 15295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 15301730e0dd28b3abc660b4e4704cf6d414f7fd4ad6Chris Forbes used = false; 15315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis it_a++; 15325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (!b_at_end && (a_at_end || b_first < a_first)) { 15331b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 0, __LINE__, 15341b52022446fb65466dfcee491393670ac12aaa33Chris Forbes SHADER_CHECKER_INPUT_NOT_PRODUCED, "SC", "Vertex shader consumes input at location %d but not provided", 15351b52022446fb65466dfcee491393670ac12aaa33Chris Forbes b_first); 15365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis it_b++; 15375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 15385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned attrib_type = get_format_type(it_a->second->format); 15395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned input_type = get_fundamental_type(vs, it_b->second.type_id); 15405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 154125002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Type checking 1542f0fdde7692ffd5175435cc3bf3412b8468054f38Chris Forbes if (!(attrib_type & input_type)) { 15431b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 15441b52022446fb65466dfcee491393670ac12aaa33Chris Forbes SHADER_CHECKER_INTERFACE_TYPE_MISMATCH, "SC", 15451b52022446fb65466dfcee491393670ac12aaa33Chris Forbes "Attribute type of `%s` at location %d does not match vertex shader input type of `%s`", 15461b52022446fb65466dfcee491393670ac12aaa33Chris Forbes string_VkFormat(it_a->second->format), a_first, describe_type(vs, it_b->second.type_id).c_str()); 15475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 15485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 154925002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // OK! 15501730e0dd28b3abc660b4e4704cf6d414f7fd4ad6Chris Forbes used = true; 15515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis it_b++; 15525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 15535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 15545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 15551b52022446fb65466dfcee491393670ac12aaa33Chris Forbes return skip; 15565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 15575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1558edef66e03ed509994449d598f4fadea1a487d41bChris Forbesstatic bool validate_fs_outputs_against_render_pass(debug_report_data *report_data, shader_module const *fs, 15598da1edac0fbed13831b2f458f27c51e64d6210ffTobin Ehlis spirv_inst_iter entrypoint, VkRenderPassCreateInfo const *rpci, 15608da1edac0fbed13831b2f458f27c51e64d6210ffTobin Ehlis uint32_t subpass_index) { 1561025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes std::map<uint32_t, VkFormat> color_attachments; 15628da1edac0fbed13831b2f458f27c51e64d6210ffTobin Ehlis auto subpass = rpci->pSubpasses[subpass_index]; 15638da1edac0fbed13831b2f458f27c51e64d6210ffTobin Ehlis for (auto i = 0u; i < subpass.colorAttachmentCount; ++i) { 1564d9da90d92748c37962766868f8b0354637672c2aTobin Ehlis uint32_t attachment = subpass.pColorAttachments[i].attachment; 1565cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (attachment == VK_ATTACHMENT_UNUSED) continue; 1566d9da90d92748c37962766868f8b0354637672c2aTobin Ehlis if (rpci->pAttachments[attachment].format != VK_FORMAT_UNDEFINED) { 1567d9da90d92748c37962766868f8b0354637672c2aTobin Ehlis color_attachments[i] = rpci->pAttachments[attachment].format; 1568025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes } 1569025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes } 1570025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes 15711b52022446fb65466dfcee491393670ac12aaa33Chris Forbes bool skip = false; 15725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 157325002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // TODO: dual source blend index (spv::DecIndex, zero if not provided) 15745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 15753a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes auto outputs = collect_interface_by_location(fs, entrypoint, spv::StorageClassOutput, false); 15765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1577025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes auto it_a = outputs.begin(); 1578025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes auto it_b = color_attachments.begin(); 15795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 158025002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Walk attachment list and outputs together 1581025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes 1582025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes while ((outputs.size() > 0 && it_a != outputs.end()) || (color_attachments.size() > 0 && it_b != color_attachments.end())) { 1583025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes bool a_at_end = outputs.size() == 0 || it_a == outputs.end(); 1584025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes bool b_at_end = color_attachments.size() == 0 || it_b == color_attachments.end(); 15855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1586025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes if (!a_at_end && (b_at_end || it_a->first.first < it_b->first)) { 15871b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 15881b52022446fb65466dfcee491393670ac12aaa33Chris Forbes SHADER_CHECKER_OUTPUT_NOT_CONSUMED, "SC", 15891b52022446fb65466dfcee491393670ac12aaa33Chris Forbes "fragment shader writes to output location %d with no matching attachment", it_a->first.first); 1590025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes it_a++; 1591025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes } else if (!b_at_end && (a_at_end || it_a->first.first > it_b->first)) { 15921b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 15931b52022446fb65466dfcee491393670ac12aaa33Chris Forbes SHADER_CHECKER_INPUT_NOT_PRODUCED, "SC", "Attachment %d not written by fragment shader", it_b->first); 1594025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes it_b++; 15955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 1596025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes unsigned output_type = get_fundamental_type(fs, it_a->second.type_id); 1597025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes unsigned att_type = get_format_type(it_b->second); 15985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 159925002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Type checking 1600f0fdde7692ffd5175435cc3bf3412b8468054f38Chris Forbes if (!(output_type & att_type)) { 16011b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 16021b52022446fb65466dfcee491393670ac12aaa33Chris Forbes SHADER_CHECKER_INTERFACE_TYPE_MISMATCH, "SC", 16031b52022446fb65466dfcee491393670ac12aaa33Chris Forbes "Attachment %d of type `%s` does not match fragment shader output type of `%s`", it_b->first, 16041b52022446fb65466dfcee491393670ac12aaa33Chris Forbes string_VkFormat(it_b->second), describe_type(fs, it_a->second.type_id).c_str()); 16055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 16065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 160725002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // OK! 1608025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes it_a++; 1609025e5113963305eff75601c96eac61d2c5b57e3cChris Forbes it_b++; 16105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 16115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 16125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 16131b52022446fb65466dfcee491393670ac12aaa33Chris Forbes return skip; 16145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 16155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 161625002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// For some analyses, we need to know about all ids referenced by the static call tree of a particular entrypoint. This is 161725002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// important for identifying the set of shader resources actually used by an entrypoint, for example. 161825002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// Note: we only explore parts of the image which might actually contain ids we care about for the above analyses. 161925002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// - NOT the shader input/output interfaces. 162025002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// 162125002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// TODO: The set of interesting opcodes here was determined by eyeballing the SPIRV spec. It might be worth 162225002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// converting parts of this to be generated from the machine-readable spec instead. 16233a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbesstatic std::unordered_set<uint32_t> mark_accessible_ids(shader_module const *src, spirv_inst_iter entrypoint) { 16243a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes std::unordered_set<uint32_t> ids; 16255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_set<uint32_t> worklist; 16265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis worklist.insert(entrypoint.word(2)); 16275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 16285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis while (!worklist.empty()) { 16295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto id_iter = worklist.begin(); 16305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto id = *id_iter; 16315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis worklist.erase(id_iter); 16325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 16335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto insn = src->get_def(id); 16345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn == src->end()) { 163525002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // ID is something we didn't collect in build_def_index. that's OK -- we'll stumble across all kinds of things here 163625002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // that we may not care about. 16375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis continue; 16385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 16395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 164025002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Try to add to the output set 16415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!ids.insert(id).second) { 1642cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski continue; // If we already saw this id, we don't want to walk it again. 16435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 16445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 16455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis switch (insn.opcode()) { 1646cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpFunction: 1647cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Scan whole body of the function, enlisting anything interesting 1648cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski while (++insn, insn.opcode() != spv::OpFunctionEnd) { 1649cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski switch (insn.opcode()) { 1650cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpLoad: 1651cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicLoad: 1652cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicExchange: 1653cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicCompareExchange: 1654cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicCompareExchangeWeak: 1655cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicIIncrement: 1656cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicIDecrement: 1657cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicIAdd: 1658cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicISub: 1659cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicSMin: 1660cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicUMin: 1661cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicSMax: 1662cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicUMax: 1663cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicAnd: 1664cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicOr: 1665cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicXor: 1666cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski worklist.insert(insn.word(3)); // ptr 1667cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1668cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpStore: 1669cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAtomicStore: 1670cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski worklist.insert(insn.word(1)); // ptr 1671cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1672cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpAccessChain: 1673cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpInBoundsAccessChain: 1674cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski worklist.insert(insn.word(3)); // base ptr 1675cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1676cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpSampledImage: 1677cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSampleImplicitLod: 1678cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSampleExplicitLod: 1679cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSampleDrefImplicitLod: 1680cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSampleDrefExplicitLod: 1681cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSampleProjImplicitLod: 1682cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSampleProjExplicitLod: 1683cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSampleProjDrefImplicitLod: 1684cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSampleProjDrefExplicitLod: 1685cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageFetch: 1686cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageGather: 1687cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageDrefGather: 1688cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageRead: 1689cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImage: 1690cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageQueryFormat: 1691cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageQueryOrder: 1692cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageQuerySizeLod: 1693cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageQuerySize: 1694cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageQueryLod: 1695cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageQueryLevels: 1696cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageQuerySamples: 1697cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSparseSampleImplicitLod: 1698cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSparseSampleExplicitLod: 1699cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSparseSampleDrefImplicitLod: 1700cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSparseSampleDrefExplicitLod: 1701cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSparseSampleProjImplicitLod: 1702cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSparseSampleProjExplicitLod: 1703cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSparseSampleProjDrefImplicitLod: 1704cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSparseSampleProjDrefExplicitLod: 1705cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSparseFetch: 1706cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSparseGather: 1707cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageSparseDrefGather: 1708cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageTexelPointer: 1709cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski worklist.insert(insn.word(3)); // Image or sampled image 1710cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1711cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpImageWrite: 1712cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski worklist.insert(insn.word(1)); // Image -- different operand order to above 1713cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 1714cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpFunctionCall: 1715cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski for (uint32_t i = 3; i < insn.len(); i++) { 1716cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski worklist.insert(insn.word(i)); // fn itself, and all args 1717cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 1718cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 17195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1720cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpExtInst: 1721cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski for (uint32_t i = 5; i < insn.len(); i++) { 1722cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski worklist.insert(insn.word(i)); // Operands to ext inst 1723cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 1724cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 17255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 1727cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 17285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17303a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes 17313a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes return ids; 17325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 17335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1734edef66e03ed509994449d598f4fadea1a487d41bChris Forbesstatic bool validate_push_constant_block_against_pipeline(debug_report_data *report_data, 1735416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis std::vector<VkPushConstantRange> const *push_constant_ranges, 17365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis shader_module const *src, spirv_inst_iter type, 17375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkShaderStageFlagBits stage) { 17381b52022446fb65466dfcee491393670ac12aaa33Chris Forbes bool skip = false; 17395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 174025002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Strip off ptrs etc 17415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis type = get_struct_type(src, type, false); 17425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(type != src->end()); 17435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 174425002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Validate directly off the offsets. this isn't quite correct for arrays and matrices, but is a good first step. 174525002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // TODO: arrays, matrices, weird sizes 17465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto insn : *src) { 17475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.opcode() == spv::OpMemberDecorate && insn.word(1) == type.word(1)) { 17485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (insn.word(3) == spv::DecorationOffset) { 17495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unsigned offset = insn.word(4); 1750cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski auto size = 4; // Bytes; TODO: calculate this based on the type 17515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 17525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool found_range = false; 1753416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis for (auto const &range : *push_constant_ranges) { 17545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (range.offset <= offset && range.offset + range.size >= offset + size) { 17555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis found_range = true; 17565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 17575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if ((range.stageFlags & stage) == 0) { 17581b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 17591b52022446fb65466dfcee491393670ac12aaa33Chris Forbes __LINE__, SHADER_CHECKER_PUSH_CONSTANT_NOT_ACCESSIBLE_FROM_STAGE, "SC", 17601b52022446fb65466dfcee491393670ac12aaa33Chris Forbes "Push constant range covering variable starting at " 17611b52022446fb65466dfcee491393670ac12aaa33Chris Forbes "offset %u not accessible from stage %s", 17621b52022446fb65466dfcee491393670ac12aaa33Chris Forbes offset, string_VkShaderStageFlagBits(stage)); 17635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 17655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis break; 17665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 17695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!found_range) { 17701b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 17711b52022446fb65466dfcee491393670ac12aaa33Chris Forbes __LINE__, SHADER_CHECKER_PUSH_CONSTANT_OUT_OF_RANGE, "SC", 17721b52022446fb65466dfcee491393670ac12aaa33Chris Forbes "Push constant range covering variable starting at " 17731b52022446fb65466dfcee491393670ac12aaa33Chris Forbes "offset %u not declared in layout", 17741b52022446fb65466dfcee491393670ac12aaa33Chris Forbes offset); 17755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 17801b52022446fb65466dfcee491393670ac12aaa33Chris Forbes return skip; 17815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 17825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1783edef66e03ed509994449d598f4fadea1a487d41bChris Forbesstatic bool validate_push_constant_usage(debug_report_data *report_data, 1784416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis std::vector<VkPushConstantRange> const *push_constant_ranges, shader_module const *src, 17855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_set<uint32_t> accessible_ids, VkShaderStageFlagBits stage) { 17861b52022446fb65466dfcee491393670ac12aaa33Chris Forbes bool skip = false; 17875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 17885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto id : accessible_ids) { 17895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto def_insn = src->get_def(id); 17905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (def_insn.opcode() == spv::OpVariable && def_insn.word(3) == spv::StorageClassPushConstant) { 17911b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= validate_push_constant_block_against_pipeline(report_data, push_constant_ranges, src, 1792416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis src->get_def(def_insn.word(1)), stage); 17935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 17955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 17961b52022446fb65466dfcee491393670ac12aaa33Chris Forbes return skip; 17975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 17985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1799fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis// For given pipelineLayout verify that the set_layout_node at slot.first 1800fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis// has the requested binding at slot.second and return ptr to that binding 1801bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic VkDescriptorSetLayoutBinding const *get_descriptor_binding(PIPELINE_LAYOUT_NODE const *pipelineLayout, 1802bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski descriptor_slot_t slot) { 1803cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!pipelineLayout) return nullptr; 18045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1805cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (slot.first >= pipelineLayout->set_layouts.size()) return nullptr; 18065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1807416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis return pipelineLayout->set_layouts[slot.first]->GetDescriptorSetLayoutBindingPtrFromBinding(slot.second); 18085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 18095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 18105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Check object status for selected flag state 181151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool validate_status(layer_data *dev_data, GLOBAL_CB_NODE *pNode, CBStatusFlags status_mask, VkFlags msg_flags, 18124f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes const char *fail_msg, UNIQUE_VALIDATION_ERROR_CODE const msg_code) { 18133d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis if (!(pNode->status & status_mask)) { 18144f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes char const *const message = validation_error_map[msg_code]; 181551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis return log_msg(dev_data->report_data, msg_flags, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 18164f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes reinterpret_cast<const uint64_t &>(pNode->commandBuffer), __LINE__, msg_code, "DS", 18174f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "command buffer object 0x%p: %s. %s.", pNode->commandBuffer, fail_msg, message); 18185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 1819e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves return false; 18205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 18215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 18225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Retrieve pipeline node ptr for given pipeline object 182351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic PIPELINE_STATE *getPipelineState(layer_data const *dev_data, VkPipeline pipeline) { 182451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis auto it = dev_data->pipelineMap.find(pipeline); 182551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (it == dev_data->pipelineMap.end()) { 1826ea8349eeee76ae2859c10870fd8bd9e60309eb28Chris Forbes return nullptr; 18275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 1828ea8349eeee76ae2859c10870fd8bd9e60309eb28Chris Forbes return it->second; 18295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 18305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 18319a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisRENDER_PASS_STATE *GetRenderPassState(layer_data const *dev_data, VkRenderPass renderpass) { 183251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis auto it = dev_data->renderPassMap.find(renderpass); 183351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (it == dev_data->renderPassMap.end()) { 183416387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes return nullptr; 183516387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes } 1836fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes return it->second.get(); 183716387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes} 183816387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes 18399a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisFRAMEBUFFER_STATE *GetFramebufferState(const layer_data *dev_data, VkFramebuffer framebuffer) { 184051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis auto it = dev_data->frameBufferMap.find(framebuffer); 184151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (it == dev_data->frameBufferMap.end()) { 1842f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes return nullptr; 1843f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes } 184404861caca7eb93a5241b164e8480bb93c826902cTobin Ehlis return it->second.get(); 1845f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes} 1846f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes 18479a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehliscvdescriptorset::DescriptorSetLayout const *GetDescriptorSetLayout(layer_data const *dev_data, VkDescriptorSetLayout dsLayout) { 184851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis auto it = dev_data->descriptorSetLayoutMap.find(dsLayout); 184951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (it == dev_data->descriptorSetLayoutMap.end()) { 185011f1fde2721c198a619e4a22fff60eef9a16fae8Chris Forbes return nullptr; 185111f1fde2721c198a619e4a22fff60eef9a16fae8Chris Forbes } 185211f1fde2721c198a619e4a22fff60eef9a16fae8Chris Forbes return it->second; 185311f1fde2721c198a619e4a22fff60eef9a16fae8Chris Forbes} 185411f1fde2721c198a619e4a22fff60eef9a16fae8Chris Forbes 185551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic PIPELINE_LAYOUT_NODE const *getPipelineLayout(layer_data const *dev_data, VkPipelineLayout pipeLayout) { 185651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis auto it = dev_data->pipelineLayoutMap.find(pipeLayout); 185751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (it == dev_data->pipelineLayoutMap.end()) { 18584a45a42023b281f55953222c1a6c3e80f50e5f2aChris Forbes return nullptr; 18594a45a42023b281f55953222c1a6c3e80f50e5f2aChris Forbes } 18604a45a42023b281f55953222c1a6c3e80f50e5f2aChris Forbes return &it->second; 18614a45a42023b281f55953222c1a6c3e80f50e5f2aChris Forbes} 18624a45a42023b281f55953222c1a6c3e80f50e5f2aChris Forbes 1863e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves// Return true if for a given PSO, the given state enum is dynamic, else return false 18644c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlisstatic bool isDynamic(const PIPELINE_STATE *pPipeline, const VkDynamicState state) { 18655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pPipeline && pPipeline->graphicsPipelineCI.pDynamicState) { 18665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < pPipeline->graphicsPipelineCI.pDynamicState->dynamicStateCount; i++) { 1867cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (state == pPipeline->graphicsPipelineCI.pDynamicState->pDynamicStates[i]) return true; 18685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 18695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 1870e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves return false; 18715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 18725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 18735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Validate state stored as flags at time of draw call 18744f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayesstatic bool validate_draw_state_flags(layer_data *dev_data, GLOBAL_CB_NODE *pCB, const PIPELINE_STATE *pPipe, bool indexed, 18754f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes UNIQUE_VALIDATION_ERROR_CODE const msg_code) { 18769c4006684a13db43f0dbc8d0015a9ef34872ca09Chris Forbes bool result = false; 1877ca546210846c65808717f8875deae39bd227c240Tobin Ehlis if (pPipe->graphicsPipelineCI.pInputAssemblyState && 1878ca546210846c65808717f8875deae39bd227c240Tobin Ehlis ((pPipe->graphicsPipelineCI.pInputAssemblyState->topology == VK_PRIMITIVE_TOPOLOGY_LINE_LIST) || 1879ca546210846c65808717f8875deae39bd227c240Tobin Ehlis (pPipe->graphicsPipelineCI.pInputAssemblyState->topology == VK_PRIMITIVE_TOPOLOGY_LINE_STRIP))) { 18803d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis result |= validate_status(dev_data, pCB, CBSTATUS_LINE_WIDTH_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, 18814f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "Dynamic line width state not set for this command buffer", msg_code); 18823d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 188345824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves if (pPipe->graphicsPipelineCI.pRasterizationState && 188445824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves (pPipe->graphicsPipelineCI.pRasterizationState->depthBiasEnable == VK_TRUE)) { 18853d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis result |= validate_status(dev_data, pCB, CBSTATUS_DEPTH_BIAS_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, 18864f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "Dynamic depth bias state not set for this command buffer", msg_code); 18873d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 18883d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis if (pPipe->blendConstantsEnabled) { 18893d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis result |= validate_status(dev_data, pCB, CBSTATUS_BLEND_CONSTANTS_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, 18904f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "Dynamic blend constants state not set for this command buffer", msg_code); 18913d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 189245824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves if (pPipe->graphicsPipelineCI.pDepthStencilState && 189345824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves (pPipe->graphicsPipelineCI.pDepthStencilState->depthBoundsTestEnable == VK_TRUE)) { 18943d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis result |= validate_status(dev_data, pCB, CBSTATUS_DEPTH_BOUNDS_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, 18954f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "Dynamic depth bounds state not set for this command buffer", msg_code); 18963d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 189745824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves if (pPipe->graphicsPipelineCI.pDepthStencilState && 189845824955f3d4d2baee6d225f84ac9c2553981b3eDustin Graves (pPipe->graphicsPipelineCI.pDepthStencilState->stencilTestEnable == VK_TRUE)) { 18993d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis result |= validate_status(dev_data, pCB, CBSTATUS_STENCIL_READ_MASK_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, 19004f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "Dynamic stencil read mask state not set for this command buffer", msg_code); 19013d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis result |= validate_status(dev_data, pCB, CBSTATUS_STENCIL_WRITE_MASK_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, 19024f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "Dynamic stencil write mask state not set for this command buffer", msg_code); 19033d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis result |= validate_status(dev_data, pCB, CBSTATUS_STENCIL_REFERENCE_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, 19044f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "Dynamic stencil reference state not set for this command buffer", msg_code); 19053d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 19061c130ea631a82716dc7334de17767536525f2292Tobin Ehlis if (indexed) { 19073d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis result |= validate_status(dev_data, pCB, CBSTATUS_INDEX_BUFFER_BOUND, VK_DEBUG_REPORT_ERROR_BIT_EXT, 19084f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes "Index buffer object not bound to this command buffer when Indexed Draw attempted", msg_code); 19093d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 19104f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes 19115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 19125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 19135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 19145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Verify attachment reference compatibility according to spec 19155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// If one array is larger, treat missing elements of shorter array as VK_ATTACHMENT_UNUSED & other array much match this 19165ca3c071afc98f9144f489b74aa3affaa93633b0Mark Lobodzinski// If both AttachmentReference arrays have requested index, check their corresponding AttachmentDescriptions 19175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// to make sure that format and samples counts match. 19185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// If not, they are not compatible. 19195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic bool attachment_references_compatible(const uint32_t index, const VkAttachmentReference *pPrimary, 19205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const uint32_t primaryCount, const VkAttachmentDescription *pPrimaryAttachments, 19215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkAttachmentReference *pSecondary, const uint32_t secondaryCount, 19225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkAttachmentDescription *pSecondaryAttachments) { 1923e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis // Check potential NULL cases first to avoid nullptr issues later 1924e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis if (pPrimary == nullptr) { 1925e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis if (pSecondary == nullptr) { 1926e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis return true; 1927e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis } 1928e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis return false; 1929e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis } else if (pSecondary == nullptr) { 1930e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis return false; 1931e62f2e46eeffde494c0d734964b389c09dec9d64Tobin Ehlis } 1932cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (index >= primaryCount) { // Check secondary as if primary is VK_ATTACHMENT_UNUSED 1933cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (VK_ATTACHMENT_UNUSED == pSecondary[index].attachment) return true; 1934cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else if (index >= secondaryCount) { // Check primary as if secondary is VK_ATTACHMENT_UNUSED 1935cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (VK_ATTACHMENT_UNUSED == pPrimary[index].attachment) return true; 1936cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else { // Format and sample count must match 19375ca3c071afc98f9144f489b74aa3affaa93633b0Mark Lobodzinski if ((pPrimary[index].attachment == VK_ATTACHMENT_UNUSED) && (pSecondary[index].attachment == VK_ATTACHMENT_UNUSED)) { 19385ca3c071afc98f9144f489b74aa3affaa93633b0Mark Lobodzinski return true; 19395ca3c071afc98f9144f489b74aa3affaa93633b0Mark Lobodzinski } else if ((pPrimary[index].attachment == VK_ATTACHMENT_UNUSED) || (pSecondary[index].attachment == VK_ATTACHMENT_UNUSED)) { 19405ca3c071afc98f9144f489b74aa3affaa93633b0Mark Lobodzinski return false; 19415ca3c071afc98f9144f489b74aa3affaa93633b0Mark Lobodzinski } 19425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if ((pPrimaryAttachments[pPrimary[index].attachment].format == 19435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pSecondaryAttachments[pSecondary[index].attachment].format) && 19445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (pPrimaryAttachments[pPrimary[index].attachment].samples == 19455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pSecondaryAttachments[pSecondary[index].attachment].samples)) 19465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return true; 19475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 19485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Format and sample counts didn't match 19495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 19505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 1951a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis// TODO : Scrub verify_renderpass_compatibility() and validateRenderPassCompatibility() and unify them and/or share code 1952266231a5421564c314f6b5d5bd3fed26fd389484Chris Forbes// For given primary RenderPass object and secondary RenderPassCreateInfo, verify that they're compatible 195351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool verify_renderpass_compatibility(const layer_data *dev_data, const VkRenderPassCreateInfo *primaryRPCI, 19548da1edac0fbed13831b2f458f27c51e64d6210ffTobin Ehlis const VkRenderPassCreateInfo *secondaryRPCI, string &errorMsg) { 19555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (primaryRPCI->subpassCount != secondaryRPCI->subpassCount) { 1956c07fa78efa7d4edfaa4ffbb0c2046ee8154b27beChris Forbes stringstream errorStr; 19575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis errorStr << "RenderPass for primary cmdBuffer has " << primaryRPCI->subpassCount 19585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis << " subpasses but renderPass for secondary cmdBuffer has " << secondaryRPCI->subpassCount << " subpasses."; 19595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis errorMsg = errorStr.str(); 19605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 19615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 19625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t spIndex = 0; 19635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (spIndex = 0; spIndex < primaryRPCI->subpassCount; ++spIndex) { 19645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // For each subpass, verify that corresponding color, input, resolve & depth/stencil attachment references are compatible 19655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t primaryColorCount = primaryRPCI->pSubpasses[spIndex].colorAttachmentCount; 19665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t secondaryColorCount = secondaryRPCI->pSubpasses[spIndex].colorAttachmentCount; 19675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t colorMax = std::max(primaryColorCount, secondaryColorCount); 19685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t cIdx = 0; cIdx < colorMax; ++cIdx) { 19695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!attachment_references_compatible(cIdx, primaryRPCI->pSubpasses[spIndex].pColorAttachments, primaryColorCount, 19705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis primaryRPCI->pAttachments, secondaryRPCI->pSubpasses[spIndex].pColorAttachments, 19715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis secondaryColorCount, secondaryRPCI->pAttachments)) { 1972c07fa78efa7d4edfaa4ffbb0c2046ee8154b27beChris Forbes stringstream errorStr; 19735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis errorStr << "color attachments at index " << cIdx << " of subpass index " << spIndex << " are not compatible."; 19745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis errorMsg = errorStr.str(); 19755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 19765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (!attachment_references_compatible(cIdx, primaryRPCI->pSubpasses[spIndex].pResolveAttachments, 19775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis primaryColorCount, primaryRPCI->pAttachments, 19785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis secondaryRPCI->pSubpasses[spIndex].pResolveAttachments, 19795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis secondaryColorCount, secondaryRPCI->pAttachments)) { 1980c07fa78efa7d4edfaa4ffbb0c2046ee8154b27beChris Forbes stringstream errorStr; 19815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis errorStr << "resolve attachments at index " << cIdx << " of subpass index " << spIndex << " are not compatible."; 19825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis errorMsg = errorStr.str(); 19835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 19845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 19855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 1986fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes 1987bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (!attachment_references_compatible(0, primaryRPCI->pSubpasses[spIndex].pDepthStencilAttachment, 1, 1988bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski primaryRPCI->pAttachments, secondaryRPCI->pSubpasses[spIndex].pDepthStencilAttachment, 1989fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes 1, secondaryRPCI->pAttachments)) { 1990c07fa78efa7d4edfaa4ffbb0c2046ee8154b27beChris Forbes stringstream errorStr; 1991fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes errorStr << "depth/stencil attachments of subpass index " << spIndex << " are not compatible."; 1992fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes errorMsg = errorStr.str(); 1993fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes return false; 1994fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes } 1995fd50683af1a7a54c6b8c13d790ad57c48072f55bChris Forbes 19965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t primaryInputCount = primaryRPCI->pSubpasses[spIndex].inputAttachmentCount; 19975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t secondaryInputCount = secondaryRPCI->pSubpasses[spIndex].inputAttachmentCount; 19985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t inputMax = std::max(primaryInputCount, secondaryInputCount); 19995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < inputMax; ++i) { 20005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!attachment_references_compatible(i, primaryRPCI->pSubpasses[spIndex].pInputAttachments, primaryColorCount, 20015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis primaryRPCI->pAttachments, secondaryRPCI->pSubpasses[spIndex].pInputAttachments, 20025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis secondaryColorCount, secondaryRPCI->pAttachments)) { 2003c07fa78efa7d4edfaa4ffbb0c2046ee8154b27beChris Forbes stringstream errorStr; 20045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis errorStr << "input attachments at index " << i << " of subpass index " << spIndex << " are not compatible."; 20055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis errorMsg = errorStr.str(); 20065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 20075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 20085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 20095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 20105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return true; 20115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 20125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2013397d27da37095073c8b86f9ff5289d0a39ce486eTobin Ehlis// For given cvdescriptorset::DescriptorSet, verify that its Set is compatible w/ the setLayout corresponding to 2014397d27da37095073c8b86f9ff5289d0a39ce486eTobin Ehlis// pipelineLayout[layoutIndex] 201512b7fc342b53fbdd399aae4a85959e37685936acChris Forbesstatic bool verify_set_layout_compatibility(const cvdescriptorset::DescriptorSet *descriptor_set, 201669b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis PIPELINE_LAYOUT_NODE const *pipeline_layout, const uint32_t layoutIndex, 201769b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis string &errorMsg) { 2018416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis auto num_sets = pipeline_layout->set_layouts.size(); 20199b5d124aff50234cb0450e1b805baef577c90d83Tobin Ehlis if (layoutIndex >= num_sets) { 2020c07fa78efa7d4edfaa4ffbb0c2046ee8154b27beChris Forbes stringstream errorStr; 202169b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis errorStr << "VkPipelineLayout (" << pipeline_layout->layout << ") only contains " << num_sets 202269b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis << " setLayouts corresponding to sets 0-" << num_sets - 1 << ", but you're attempting to bind set to index " 202369b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis << layoutIndex; 20245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis errorMsg = errorStr.str(); 20255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 20265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 2027416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis auto layout_node = pipeline_layout->set_layouts[layoutIndex]; 20281c130ea631a82716dc7334de17767536525f2292Tobin Ehlis return descriptor_set->IsCompatible(layout_node, &errorMsg); 20295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 20305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 20315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Validate that data for each specialization entry is fully contained within the buffer. 2032edef66e03ed509994449d598f4fadea1a487d41bChris Forbesstatic bool validate_specialization_offsets(debug_report_data *report_data, VkPipelineShaderStageCreateInfo const *info) { 20331b52022446fb65466dfcee491393670ac12aaa33Chris Forbes bool skip = false; 20345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 20355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkSpecializationInfo const *spec = info->pSpecializationInfo; 20365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 20375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (spec) { 20385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto i = 0u; i < spec->mapEntryCount; i++) { 20394f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes // TODO: This is a good place for VALIDATION_ERROR_00589. 20405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (spec->pMapEntries[i].offset + spec->pMapEntries[i].size > spec->dataSize) { 20411b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 0, __LINE__, 20421b52022446fb65466dfcee491393670ac12aaa33Chris Forbes VALIDATION_ERROR_00590, "SC", 20431b52022446fb65466dfcee491393670ac12aaa33Chris Forbes "Specialization entry %u (for constant id %u) references memory outside provided " 20441b52022446fb65466dfcee491393670ac12aaa33Chris Forbes "specialization data (bytes %u.." PRINTF_SIZE_T_SPECIFIER "; " PRINTF_SIZE_T_SPECIFIER 20451b52022446fb65466dfcee491393670ac12aaa33Chris Forbes " bytes provided). %s.", 20461b52022446fb65466dfcee491393670ac12aaa33Chris Forbes i, spec->pMapEntries[i].constantID, spec->pMapEntries[i].offset, 20471b52022446fb65466dfcee491393670ac12aaa33Chris Forbes spec->pMapEntries[i].offset + spec->pMapEntries[i].size - 1, spec->dataSize, 20481b52022446fb65466dfcee491393670ac12aaa33Chris Forbes validation_error_map[VALIDATION_ERROR_00590]); 20495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 20505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 20515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 20525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 20531b52022446fb65466dfcee491393670ac12aaa33Chris Forbes return skip; 20545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 20555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2056bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic bool descriptor_type_match(shader_module const *module, uint32_t type_id, VkDescriptorType descriptor_type, 2057bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski unsigned &descriptor_count) { 20585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto type = module->get_def(type_id); 20595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 20601b8c581791ac3c05d7829e04a2d8ecb964b8f2a6Chris Forbes descriptor_count = 1; 20611b8c581791ac3c05d7829e04a2d8ecb964b8f2a6Chris Forbes 206225002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Strip off any array or ptrs. Where we remove array levels, adjust the descriptor count for each dimension. 20635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis while (type.opcode() == spv::OpTypeArray || type.opcode() == spv::OpTypePointer) { 20647b892d2fc502b57d26dc9bff61b0f23cccc595fdChris Forbes if (type.opcode() == spv::OpTypeArray) { 20657b892d2fc502b57d26dc9bff61b0f23cccc595fdChris Forbes descriptor_count *= get_constant_value(module, type.word(3)); 20667b892d2fc502b57d26dc9bff61b0f23cccc595fdChris Forbes type = module->get_def(type.word(2)); 2067bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski } else { 20687b892d2fc502b57d26dc9bff61b0f23cccc595fdChris Forbes type = module->get_def(type.word(3)); 20697b892d2fc502b57d26dc9bff61b0f23cccc595fdChris Forbes } 20705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 20715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 20725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis switch (type.opcode()) { 2073cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeStruct: { 2074cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski for (auto insn : *module) { 2075cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (insn.opcode() == spv::OpDecorate && insn.word(1) == type.word(1)) { 2076cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (insn.word(2) == spv::DecorationBlock) { 2077cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER || 2078cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; 2079cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else if (insn.word(2) == spv::DecorationBufferBlock) { 2080cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER || 2081cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC; 2082cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 20835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 20845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 20855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2086cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Invalid 2087cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return false; 2088cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 20895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2090cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeSampler: 2091cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return descriptor_type == VK_DESCRIPTOR_TYPE_SAMPLER || descriptor_type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 20925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2093cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeSampledImage: 2094cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER) { 2095cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Slight relaxation for some GLSL historical madness: samplerBuffer doesn't really have a sampler, and a texel 2096cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // buffer descriptor doesn't really provide one. Allow this slight mismatch. 2097cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski auto image_type = module->get_def(type.word(2)); 2098cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski auto dim = image_type.word(3); 2099cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski auto sampled = image_type.word(7); 2100cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return dim == spv::DimBuffer && sampled == 1; 2101cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 2102cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return descriptor_type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 21035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2104cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeImage: { 2105cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Many descriptor types backing image types-- depends on dimension and whether the image will be used with a sampler. 2106cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // SPIRV for Vulkan requires that sampled be 1 or 2 -- leaving the decision to runtime is unacceptable. 2107cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski auto dim = type.word(3); 2108cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski auto sampled = type.word(7); 21095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2110cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dim == spv::DimSubpassData) { 2111cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return descriptor_type == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; 2112cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else if (dim == spv::DimBuffer) { 2113cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (sampled == 1) { 2114cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; 2115cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else { 2116cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; 2117cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 2118cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else if (sampled == 1) { 2119cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return descriptor_type == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE || 2120cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski descriptor_type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 21215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 2122cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; 21235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 21245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 21255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2126cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // We shouldn't really see any other junk types -- but if we do, they're a mismatch. 2127cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 2128cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return false; // Mismatch 21295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 21305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 21315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 21324110a6be7a8a287d459475926985f71c27d01298Chris Forbesstatic bool require_feature(debug_report_data *report_data, VkBool32 feature, char const *feature_name) { 2133a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes if (!feature) { 21345b9ab1fb8720c30edfbe8dd974e2364425471ad5Mark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 2135cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski SHADER_CHECKER_FEATURE_NOT_ENABLED, "SC", 2136cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Shader requires VkPhysicalDeviceFeatures::%s but is not " 2137cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "enabled on the device", 2138a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes feature_name)) { 21391b52022446fb65466dfcee491393670ac12aaa33Chris Forbes return true; 2140a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes } 2141a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes } 2142a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 21431b52022446fb65466dfcee491393670ac12aaa33Chris Forbes return false; 2144a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes} 2145a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 214659e12b842592a05706886ab852b767ba251d9467Chris Forbesstatic bool require_extension(debug_report_data *report_data, bool extension, char const *extension_name) { 21477b6006f355aaacf7fc7f0d575b40285b89ecd279Chris Forbes if (!extension) { 21485b9ab1fb8720c30edfbe8dd974e2364425471ad5Mark Lobodzinski if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 21497b6006f355aaacf7fc7f0d575b40285b89ecd279Chris Forbes SHADER_CHECKER_FEATURE_NOT_ENABLED, "SC", 21507b6006f355aaacf7fc7f0d575b40285b89ecd279Chris Forbes "Shader requires extension %s but is not " 21517b6006f355aaacf7fc7f0d575b40285b89ecd279Chris Forbes "enabled on the device", 21527b6006f355aaacf7fc7f0d575b40285b89ecd279Chris Forbes extension_name)) { 21531b52022446fb65466dfcee491393670ac12aaa33Chris Forbes return true; 21547b6006f355aaacf7fc7f0d575b40285b89ecd279Chris Forbes } 21557b6006f355aaacf7fc7f0d575b40285b89ecd279Chris Forbes } 21567b6006f355aaacf7fc7f0d575b40285b89ecd279Chris Forbes 21571b52022446fb65466dfcee491393670ac12aaa33Chris Forbes return false; 21587b6006f355aaacf7fc7f0d575b40285b89ecd279Chris Forbes} 21597b6006f355aaacf7fc7f0d575b40285b89ecd279Chris Forbes 2160ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbesstatic bool validate_shader_capabilities(layer_data *dev_data, shader_module const *src) { 21611b52022446fb65466dfcee491393670ac12aaa33Chris Forbes bool skip = false; 2162a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2163ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes auto report_data = dev_data->report_data; 2164ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes auto const & enabledFeatures = dev_data->enabled_features; 2165ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes 2166a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes for (auto insn : *src) { 2167a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes if (insn.opcode() == spv::OpCapability) { 2168a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes switch (insn.word(1)) { 2169cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityMatrix: 2170cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityShader: 2171cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityInputAttachment: 2172cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilitySampled1D: 2173cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityImage1D: 2174cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilitySampledBuffer: 2175cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityImageBuffer: 2176cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityImageQuery: 2177cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityDerivativeControl: 2178cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Always supported by a Vulkan 1.0 implementation -- no feature bits. 2179cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2180a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2181cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityGeometry: 21821b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= require_feature(report_data, enabledFeatures.geometryShader, "geometryShader"); 2183cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2184a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2185cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityTessellation: 21861b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= require_feature(report_data, enabledFeatures.tessellationShader, "tessellationShader"); 2187cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2188a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2189cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityFloat64: 21901b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= require_feature(report_data, enabledFeatures.shaderFloat64, "shaderFloat64"); 2191cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2192a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2193cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityInt64: 21941b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= require_feature(report_data, enabledFeatures.shaderInt64, "shaderInt64"); 2195cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2196a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2197cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityTessellationPointSize: 2198cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityGeometryPointSize: 21991b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= require_feature(report_data, enabledFeatures.shaderTessellationAndGeometryPointSize, 2200cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "shaderTessellationAndGeometryPointSize"); 2201cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2202a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2203cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityImageGatherExtended: 22041b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= require_feature(report_data, enabledFeatures.shaderImageGatherExtended, "shaderImageGatherExtended"); 2205cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2206a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2207cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityStorageImageMultisample: 22081b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= require_feature(report_data, enabledFeatures.shaderStorageImageMultisample, 2209cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "shaderStorageImageMultisample"); 2210cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2211a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2212cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityUniformBufferArrayDynamicIndexing: 22131b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= require_feature(report_data, enabledFeatures.shaderUniformBufferArrayDynamicIndexing, 2214cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "shaderUniformBufferArrayDynamicIndexing"); 2215cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2216a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2217cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilitySampledImageArrayDynamicIndexing: 22181b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= require_feature(report_data, enabledFeatures.shaderSampledImageArrayDynamicIndexing, 2219cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "shaderSampledImageArrayDynamicIndexing"); 2220cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2221a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2222cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityStorageBufferArrayDynamicIndexing: 22231b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= require_feature(report_data, enabledFeatures.shaderStorageBufferArrayDynamicIndexing, 2224cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "shaderStorageBufferArrayDynamicIndexing"); 2225cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2226a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2227cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityStorageImageArrayDynamicIndexing: 22281b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= require_feature(report_data, enabledFeatures.shaderStorageImageArrayDynamicIndexing, 2229cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "shaderStorageImageArrayDynamicIndexing"); 2230cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2231a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2232cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityClipDistance: 22331b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= require_feature(report_data, enabledFeatures.shaderClipDistance, "shaderClipDistance"); 2234cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2235a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2236cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityCullDistance: 22371b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= require_feature(report_data, enabledFeatures.shaderCullDistance, "shaderCullDistance"); 2238cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2239a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2240cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityImageCubeArray: 22411b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= require_feature(report_data, enabledFeatures.imageCubeArray, "imageCubeArray"); 2242cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2243a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2244cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilitySampleRateShading: 22451b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= require_feature(report_data, enabledFeatures.sampleRateShading, "sampleRateShading"); 2246cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2247a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2248cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilitySparseResidency: 22491b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= require_feature(report_data, enabledFeatures.shaderResourceResidency, "shaderResourceResidency"); 2250cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2251a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2252cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityMinLod: 22531b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= require_feature(report_data, enabledFeatures.shaderResourceMinLod, "shaderResourceMinLod"); 2254cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2255a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2256cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilitySampledCubeArray: 22571b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= require_feature(report_data, enabledFeatures.imageCubeArray, "imageCubeArray"); 2258cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2259a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2260cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityImageMSArray: 22611b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= require_feature(report_data, enabledFeatures.shaderStorageImageMultisample, 2262cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "shaderStorageImageMultisample"); 2263cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2264a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2265cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityStorageImageExtendedFormats: 22661b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= require_feature(report_data, enabledFeatures.shaderStorageImageExtendedFormats, 2267cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "shaderStorageImageExtendedFormats"); 2268cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2269a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2270cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityInterpolationFunction: 22711b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= require_feature(report_data, enabledFeatures.sampleRateShading, "sampleRateShading"); 2272cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2273a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2274cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityStorageImageReadWithoutFormat: 22751b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= require_feature(report_data, enabledFeatures.shaderStorageImageReadWithoutFormat, 2276cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "shaderStorageImageReadWithoutFormat"); 2277cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2278a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2279cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityStorageImageWriteWithoutFormat: 22801b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= require_feature(report_data, enabledFeatures.shaderStorageImageWriteWithoutFormat, 2281cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "shaderStorageImageWriteWithoutFormat"); 2282cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2283a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2284cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::CapabilityMultiViewport: 22851b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= require_feature(report_data, enabledFeatures.multiViewport, "multiViewport"); 2286cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2287a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 22887b6006f355aaacf7fc7f0d575b40285b89ecd279Chris Forbes case spv::CapabilityDrawParameters: 22891b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= require_extension(report_data, dev_data->device_extensions.khr_shader_draw_parameters_enabled, 22907b6006f355aaacf7fc7f0d575b40285b89ecd279Chris Forbes VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME); 22917b6006f355aaacf7fc7f0d575b40285b89ecd279Chris Forbes break; 22927b6006f355aaacf7fc7f0d575b40285b89ecd279Chris Forbes 22932664122d97c3f0a98b3e5d12833bbb20196ca837Mark Lobodzinski case spv::CapabilityGeometryShaderPassthroughNV: 22941b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= require_extension(report_data, dev_data->device_extensions.nv_geometry_shader_passthrough_enabled, 22952664122d97c3f0a98b3e5d12833bbb20196ca837Mark Lobodzinski VK_NV_GEOMETRY_SHADER_PASSTHROUGH_EXTENSION_NAME); 22962664122d97c3f0a98b3e5d12833bbb20196ca837Mark Lobodzinski break; 22972664122d97c3f0a98b3e5d12833bbb20196ca837Mark Lobodzinski 2298bd546e41d3ab1deff04a593364d3522332df179eMark Lobodzinski case spv::CapabilitySampleMaskOverrideCoverageNV: 22991b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= require_extension(report_data, dev_data->device_extensions.nv_sample_mask_override_coverage_enabled, 2300bd546e41d3ab1deff04a593364d3522332df179eMark Lobodzinski VK_NV_SAMPLE_MASK_OVERRIDE_COVERAGE_EXTENSION_NAME); 2301bd546e41d3ab1deff04a593364d3522332df179eMark Lobodzinski break; 2302bd546e41d3ab1deff04a593364d3522332df179eMark Lobodzinski 23036f82da9debd5cdeda59f388250b506c59e7d8d54Mark Lobodzinski case spv::CapabilityShaderViewportIndexLayerNV: 23046f82da9debd5cdeda59f388250b506c59e7d8d54Mark Lobodzinski case spv::CapabilityShaderViewportMaskNV: 23051b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= require_extension(report_data, dev_data->device_extensions.nv_viewport_array2_enabled, 23066f82da9debd5cdeda59f388250b506c59e7d8d54Mark Lobodzinski VK_NV_VIEWPORT_ARRAY2_EXTENSION_NAME); 23076f82da9debd5cdeda59f388250b506c59e7d8d54Mark Lobodzinski break; 23086f82da9debd5cdeda59f388250b506c59e7d8d54Mark Lobodzinski 230968774dfa273ec153ae4e65f69cca6fb16b9309feMark Lobodzinski case spv::CapabilitySubgroupBallotKHR: 23101b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= require_extension(report_data, dev_data->device_extensions.khr_subgroup_ballot_enabled, 231168774dfa273ec153ae4e65f69cca6fb16b9309feMark Lobodzinski VK_EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME); 231268774dfa273ec153ae4e65f69cca6fb16b9309feMark Lobodzinski break; 231368774dfa273ec153ae4e65f69cca6fb16b9309feMark Lobodzinski 2314ae17c7b673b9763c8e74bb70ed9e53b00aca8081Mark Lobodzinski case spv::CapabilitySubgroupVoteKHR: 23151b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= require_extension(report_data, dev_data->device_extensions.khr_subgroup_vote_enabled, 2316ae17c7b673b9763c8e74bb70ed9e53b00aca8081Mark Lobodzinski VK_EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME); 2317ae17c7b673b9763c8e74bb70ed9e53b00aca8081Mark Lobodzinski break; 2318ae17c7b673b9763c8e74bb70ed9e53b00aca8081Mark Lobodzinski 2319cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 2320436434eba4d9f91016f313c8fb1525d76d7932fcMark Lobodzinski // Spirv-validator should catch these errors 2321cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2322a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes } 2323a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes } 2324a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes } 2325a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 23261b52022446fb65466dfcee491393670ac12aaa33Chris Forbes return skip; 2327a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes} 2328a3c20a28f119d24faec013fb4513605b654c36c3Chris Forbes 2329b2a61f3cd17c68887759817059fa1872f1e1464aChris Forbesstatic uint32_t descriptor_type_to_reqs(shader_module const *module, uint32_t type_id) { 23302aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes auto type = module->get_def(type_id); 23312aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes 23322aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes while (true) { 23332aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes switch (type.opcode()) { 2334cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeArray: 2335cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeSampledImage: 2336cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski type = module->get_def(type.word(2)); 2337cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2338cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypePointer: 2339cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski type = module->get_def(type.word(3)); 2340cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 2341cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::OpTypeImage: { 2342cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski auto dim = type.word(3); 2343cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski auto arrayed = type.word(5); 2344cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski auto msaa = type.word(6); 2345cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski 2346cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski switch (dim) { 2347cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::Dim1D: 2348cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return arrayed ? DESCRIPTOR_REQ_VIEW_TYPE_1D_ARRAY : DESCRIPTOR_REQ_VIEW_TYPE_1D; 2349cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::Dim2D: 2350cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return (msaa ? DESCRIPTOR_REQ_MULTI_SAMPLE : DESCRIPTOR_REQ_SINGLE_SAMPLE) | 2351cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski (arrayed ? DESCRIPTOR_REQ_VIEW_TYPE_2D_ARRAY : DESCRIPTOR_REQ_VIEW_TYPE_2D); 2352cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::Dim3D: 2353cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return DESCRIPTOR_REQ_VIEW_TYPE_3D; 2354cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::DimCube: 2355cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return arrayed ? DESCRIPTOR_REQ_VIEW_TYPE_CUBE_ARRAY : DESCRIPTOR_REQ_VIEW_TYPE_CUBE; 2356cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case spv::DimSubpassData: 2357cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return msaa ? DESCRIPTOR_REQ_MULTI_SAMPLE : DESCRIPTOR_REQ_SINGLE_SAMPLE; 2358cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: // buffer, etc. 2359cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return 0; 2360cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 23612aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes } 2362cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 2363cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski return 0; 23642aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes } 23652aa6e0c0e34095c0c84699f98172d05750a9c587Chris Forbes } 2366b2a61f3cd17c68887759817059fa1872f1e1464aChris Forbes} 2367b2a61f3cd17c68887759817059fa1872f1e1464aChris Forbes 2368cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskistatic bool validate_pipeline_shader_stage( 2369ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes layer_data *dev_data, VkPipelineShaderStageCreateInfo const *pStage, PIPELINE_STATE *pipeline, 2370ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes shader_module **out_module, spirv_inst_iter *out_entrypoint) { 23711b52022446fb65466dfcee491393670ac12aaa33Chris Forbes bool skip = false; 2372ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes auto module_it = dev_data->shaderModuleMap.find(pStage->module); 237369f9a551bfb1fd5334950f9685c12c5adda23dfbChris Forbes auto module = *out_module = module_it->second.get(); 2374ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes auto report_data = dev_data->report_data; 237578be5018e238bd464b1f1c55138df277c0c18922Chris Forbes 23761b52022446fb65466dfcee491393670ac12aaa33Chris Forbes if (!module->has_valid_spirv) return false; 2377c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski 237825002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Find the entrypoint 237978be5018e238bd464b1f1c55138df277c0c18922Chris Forbes auto entrypoint = *out_entrypoint = find_entrypoint(module, pStage->pName, pStage->stage); 238078be5018e238bd464b1f1c55138df277c0c18922Chris Forbes if (entrypoint == module->end()) { 23815b9ab1fb8720c30edfbe8dd974e2364425471ad5Mark Lobodzinski if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 23825b9ab1fb8720c30edfbe8dd974e2364425471ad5Mark Lobodzinski VALIDATION_ERROR_00510, "SC", "No entrypoint found named `%s` for stage %s. %s.", pStage->pName, 23834f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes string_VkShaderStageFlagBits(pStage->stage), validation_error_map[VALIDATION_ERROR_00510])) { 23841b52022446fb65466dfcee491393670ac12aaa33Chris Forbes return true; // no point continuing beyond here, any analysis is just going to be garbage. 238578be5018e238bd464b1f1c55138df277c0c18922Chris Forbes } 238678be5018e238bd464b1f1c55138df277c0c18922Chris Forbes } 238778be5018e238bd464b1f1c55138df277c0c18922Chris Forbes 238825002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Validate shader capabilities against enabled device features 23891b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= validate_shader_capabilities(dev_data, module); 239078be5018e238bd464b1f1c55138df277c0c18922Chris Forbes 239125002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Mark accessible ids 23923a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes auto accessible_ids = mark_accessible_ids(module, entrypoint); 239378be5018e238bd464b1f1c55138df277c0c18922Chris Forbes 239425002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Validate descriptor set layout against what the entrypoint actually uses 23953a1adf43eb19fc8e32b5cf64eab56d120d6e00e8Chris Forbes auto descriptor_uses = collect_interface_by_descriptor_slot(report_data, module, accessible_ids); 239678be5018e238bd464b1f1c55138df277c0c18922Chris Forbes 23972e0eca3d6fad72a29ae072e3895e29a2d2d66476Tobin Ehlis auto pipelineLayout = pipeline->pipeline_layout; 2398ed399f66e0512ef077d0e0a7cb903248726d2424Chris Forbes 23991b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= validate_specialization_offsets(report_data, pStage); 24001b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= validate_push_constant_usage(report_data, &pipelineLayout.push_constant_ranges, module, accessible_ids, pStage->stage); 240178be5018e238bd464b1f1c55138df277c0c18922Chris Forbes 240225002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Validate descriptor use 240378be5018e238bd464b1f1c55138df277c0c18922Chris Forbes for (auto use : descriptor_uses) { 240478be5018e238bd464b1f1c55138df277c0c18922Chris Forbes // While validating shaders capture which slots are used by the pipeline 2405bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto &reqs = pipeline->active_slots[use.first.first][use.first.second]; 2406b2a61f3cd17c68887759817059fa1872f1e1464aChris Forbes reqs = descriptor_req(reqs | descriptor_type_to_reqs(module, use.second.type_id)); 240778be5018e238bd464b1f1c55138df277c0c18922Chris Forbes 240825002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Verify given pipelineLayout has requested setLayout with requested binding 2409c8268861aaa8f9c47920065d6323e4609e5081b0Tobin Ehlis const auto &binding = get_descriptor_binding(&pipelineLayout, use.first); 241078be5018e238bd464b1f1c55138df277c0c18922Chris Forbes unsigned required_descriptor_count; 241178be5018e238bd464b1f1c55138df277c0c18922Chris Forbes 241278be5018e238bd464b1f1c55138df277c0c18922Chris Forbes if (!binding) { 24131b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 24141b52022446fb65466dfcee491393670ac12aaa33Chris Forbes SHADER_CHECKER_MISSING_DESCRIPTOR, "SC", 24151b52022446fb65466dfcee491393670ac12aaa33Chris Forbes "Shader uses descriptor slot %u.%u (used as type `%s`) but not declared in pipeline layout", 24161b52022446fb65466dfcee491393670ac12aaa33Chris Forbes use.first.first, use.first.second, describe_type(module, use.second.type_id).c_str()); 241778be5018e238bd464b1f1c55138df277c0c18922Chris Forbes } else if (~binding->stageFlags & pStage->stage) { 24181b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 0, __LINE__, 24191b52022446fb65466dfcee491393670ac12aaa33Chris Forbes SHADER_CHECKER_DESCRIPTOR_NOT_ACCESSIBLE_FROM_STAGE, "SC", 24201b52022446fb65466dfcee491393670ac12aaa33Chris Forbes "Shader uses descriptor slot %u.%u (used " 24211b52022446fb65466dfcee491393670ac12aaa33Chris Forbes "as type `%s`) but descriptor not " 24221b52022446fb65466dfcee491393670ac12aaa33Chris Forbes "accessible from stage %s", 24231b52022446fb65466dfcee491393670ac12aaa33Chris Forbes use.first.first, use.first.second, describe_type(module, use.second.type_id).c_str(), 24241b52022446fb65466dfcee491393670ac12aaa33Chris Forbes string_VkShaderStageFlagBits(pStage->stage)); 2425bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski } else if (!descriptor_type_match(module, use.second.type_id, binding->descriptorType, required_descriptor_count)) { 24261b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 24271b52022446fb65466dfcee491393670ac12aaa33Chris Forbes SHADER_CHECKER_DESCRIPTOR_TYPE_MISMATCH, "SC", 24281b52022446fb65466dfcee491393670ac12aaa33Chris Forbes "Type mismatch on descriptor slot " 24291b52022446fb65466dfcee491393670ac12aaa33Chris Forbes "%u.%u (used as type `%s`) but " 24301b52022446fb65466dfcee491393670ac12aaa33Chris Forbes "descriptor of type %s", 24311b52022446fb65466dfcee491393670ac12aaa33Chris Forbes use.first.first, use.first.second, describe_type(module, use.second.type_id).c_str(), 24321b52022446fb65466dfcee491393670ac12aaa33Chris Forbes string_VkDescriptorType(binding->descriptorType)); 243378be5018e238bd464b1f1c55138df277c0c18922Chris Forbes } else if (binding->descriptorCount < required_descriptor_count) { 24341b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 24351b52022446fb65466dfcee491393670ac12aaa33Chris Forbes SHADER_CHECKER_DESCRIPTOR_TYPE_MISMATCH, "SC", 24361b52022446fb65466dfcee491393670ac12aaa33Chris Forbes "Shader expects at least %u descriptors for binding %u.%u (used as type `%s`) but only %u provided", 24371b52022446fb65466dfcee491393670ac12aaa33Chris Forbes required_descriptor_count, use.first.first, use.first.second, 24381b52022446fb65466dfcee491393670ac12aaa33Chris Forbes describe_type(module, use.second.type_id).c_str(), binding->descriptorCount); 243978be5018e238bd464b1f1c55138df277c0c18922Chris Forbes } 244078be5018e238bd464b1f1c55138df277c0c18922Chris Forbes } 244178be5018e238bd464b1f1c55138df277c0c18922Chris Forbes 244225002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Validate use of input attachments against subpass structure 2443c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes if (pStage->stage == VK_SHADER_STAGE_FRAGMENT_BIT) { 244412b7fc342b53fbdd399aae4a85959e37685936acChris Forbes auto input_attachment_uses = collect_interface_by_input_attachment_index(module, accessible_ids); 2445c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes 2446c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes auto rpci = pipeline->render_pass_ci.ptr(); 2447c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes auto subpass = pipeline->graphicsPipelineCI.subpass; 2448c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes 2449c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes for (auto use : input_attachment_uses) { 2450c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes auto input_attachments = rpci->pSubpasses[subpass].pInputAttachments; 2451bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto index = (input_attachments && use.first < rpci->pSubpasses[subpass].inputAttachmentCount) 2452bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski ? input_attachments[use.first].attachment 2453bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski : VK_ATTACHMENT_UNUSED; 2454c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes 2455c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes if (index == VK_ATTACHMENT_UNUSED) { 24561b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 24571b52022446fb65466dfcee491393670ac12aaa33Chris Forbes SHADER_CHECKER_MISSING_INPUT_ATTACHMENT, "SC", 24581b52022446fb65466dfcee491393670ac12aaa33Chris Forbes "Shader consumes input attachment index %d but not provided in subpass", use.first); 2459f0fdde7692ffd5175435cc3bf3412b8468054f38Chris Forbes } else if (!(get_format_type(rpci->pAttachments[index].format) & get_fundamental_type(module, use.second.type_id))) { 24601b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= 24611b52022446fb65466dfcee491393670ac12aaa33Chris Forbes log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 2462eeb9f6a27f1acc11e54080fb3bcda7b513b5c89fChris Forbes SHADER_CHECKER_INPUT_ATTACHMENT_TYPE_MISMATCH, "SC", 2463bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "Subpass input attachment %u format of %s does not match type used in shader `%s`", use.first, 24641b52022446fb65466dfcee491393670ac12aaa33Chris Forbes string_VkFormat(rpci->pAttachments[index].format), describe_type(module, use.second.type_id).c_str()); 2465eeb9f6a27f1acc11e54080fb3bcda7b513b5c89fChris Forbes } 2466c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes } 2467c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes } 2468c024994b70f304ed7c6a472b90803c9911be09ddChris Forbes 24691b52022446fb65466dfcee491393670ac12aaa33Chris Forbes return skip; 247078be5018e238bd464b1f1c55138df277c0c18922Chris Forbes} 247178be5018e238bd464b1f1c55138df277c0c18922Chris Forbes 2472a61b537fcb6a4f7b92cd217b3964ad7a48109da1Tobin Ehlis// Validate that the shaders used by the given pipeline and store the active_slots 2473a61b537fcb6a4f7b92cd217b3964ad7a48109da1Tobin Ehlis// that are actually used by the pipeline into pPipeline->active_slots 2474ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbesstatic bool validate_and_capture_pipeline_shader_state(layer_data *dev_data, PIPELINE_STATE *pPipeline) { 24756660d6f3e4e4c895063e8d99098162bd2f508b24Chris Forbes auto pCreateInfo = pPipeline->graphicsPipelineCI.ptr(); 24765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis int vertex_stage = get_shader_stage_id(VK_SHADER_STAGE_VERTEX_BIT); 24775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis int fragment_stage = get_shader_stage_id(VK_SHADER_STAGE_FRAGMENT_BIT); 24785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 24795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis shader_module *shaders[5]; 24805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis memset(shaders, 0, sizeof(shaders)); 24815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis spirv_inst_iter entrypoints[5]; 24825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis memset(entrypoints, 0, sizeof(entrypoints)); 24831b52022446fb65466dfcee491393670ac12aaa33Chris Forbes bool skip = false; 24845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 24855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->stageCount; i++) { 24866660d6f3e4e4c895063e8d99098162bd2f508b24Chris Forbes auto pStage = &pCreateInfo->pStages[i]; 248778be5018e238bd464b1f1c55138df277c0c18922Chris Forbes auto stage_id = get_shader_stage_id(pStage->stage); 24881b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= validate_pipeline_shader_stage(dev_data, pStage, pPipeline, &shaders[stage_id], &entrypoints[stage_id]); 24895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 24905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2491d5365427feb4a6c16371ecb651afa37b89dabd96Chris Forbes // if the shader stages are no good individually, cross-stage validation is pointless. 24921b52022446fb65466dfcee491393670ac12aaa33Chris Forbes if (skip) return true; 2493b7476f4c4998ae20e579bd2d134667b71acdbf91Chris Forbes 2494ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes auto vi = pCreateInfo->pVertexInputState; 24955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 24965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (vi) { 24971b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= validate_vi_consistency(dev_data->report_data, vi); 24985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 24995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2500c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski if (shaders[vertex_stage] && shaders[vertex_stage]->has_valid_spirv) { 25011b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= validate_vi_against_vs_inputs(dev_data->report_data, vi, shaders[vertex_stage], entrypoints[vertex_stage]); 25025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 25035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 25045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis int producer = get_shader_stage_id(VK_SHADER_STAGE_VERTEX_BIT); 25055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis int consumer = get_shader_stage_id(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT); 25065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 25075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis while (!shaders[producer] && producer != fragment_stage) { 25085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis producer++; 25095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis consumer++; 25105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 25115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 25125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (; producer != fragment_stage && consumer <= fragment_stage; consumer++) { 25135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(shaders[producer]); 2514c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski if (shaders[consumer] && shaders[consumer]->has_valid_spirv && shaders[producer]->has_valid_spirv) { 25151b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= validate_interface_between_stages(dev_data->report_data, shaders[producer], entrypoints[producer], 2516bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &shader_stage_attribs[producer], shaders[consumer], entrypoints[consumer], 2517bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &shader_stage_attribs[consumer]); 25185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 25195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis producer = consumer; 25205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 25215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 25225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2523c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski if (shaders[fragment_stage] && shaders[fragment_stage]->has_valid_spirv) { 25241b52022446fb65466dfcee491393670ac12aaa33Chris Forbes skip |= validate_fs_outputs_against_render_pass(dev_data->report_data, shaders[fragment_stage], entrypoints[fragment_stage], 25258da1edac0fbed13831b2f458f27c51e64d6210ffTobin Ehlis pPipeline->render_pass_ci.ptr(), pCreateInfo->subpass); 25265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 25275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 25281b52022446fb65466dfcee491393670ac12aaa33Chris Forbes return skip; 25295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 25305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2531ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbesstatic bool validate_compute_pipeline(layer_data *dev_data, PIPELINE_STATE *pPipeline) { 25326660d6f3e4e4c895063e8d99098162bd2f508b24Chris Forbes auto pCreateInfo = pPipeline->computePipelineCI.ptr(); 253303857e826cdc6e8d814137fb3245596ca1cb7bc7Chris Forbes 253403857e826cdc6e8d814137fb3245596ca1cb7bc7Chris Forbes shader_module *module; 253503857e826cdc6e8d814137fb3245596ca1cb7bc7Chris Forbes spirv_inst_iter entrypoint; 253603857e826cdc6e8d814137fb3245596ca1cb7bc7Chris Forbes 2537ecdfecfe60f239f0d66bc398b9172ef72497597aChris Forbes return validate_pipeline_shader_stage(dev_data, &pCreateInfo->stage, pPipeline, &module, &entrypoint); 253803857e826cdc6e8d814137fb3245596ca1cb7bc7Chris Forbes} 25395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Return Set node ptr for specified set or else NULL 25409a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehliscvdescriptorset::DescriptorSet *GetSetNode(const layer_data *dev_data, VkDescriptorSet set) { 254151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis auto set_it = dev_data->setMap.find(set); 254251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (set_it == dev_data->setMap.end()) { 25435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return NULL; 25445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 2545104ab082916e41467ef60baaab7a5a8b2e02c59cTobin Ehlis return set_it->second; 25465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 25475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2548eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young// For given pipeline, return number of MSAA samples, or one if MSAA disabled 25494c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlisstatic VkSampleCountFlagBits getNumSamples(PIPELINE_STATE const *pipe) { 2550ea8349eeee76ae2859c10870fd8bd9e60309eb28Chris Forbes if (pipe->graphicsPipelineCI.pMultisampleState != NULL && 2551ea8349eeee76ae2859c10870fd8bd9e60309eb28Chris Forbes VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO == pipe->graphicsPipelineCI.pMultisampleState->sType) { 2552eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young return pipe->graphicsPipelineCI.pMultisampleState->rasterizationSamples; 2553eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young } 2554eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young return VK_SAMPLE_COUNT_1_BIT; 2555eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young} 2556eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young 2557bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic void list_bits(std::ostream &s, uint32_t bits) { 2558b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes for (int i = 0; i < 32 && bits; i++) { 2559b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes if (bits & (1 << i)) { 2560b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes s << i; 2561b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes bits &= ~(1 << i); 2562b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes if (bits) { 2563b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes s << ","; 2564b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes } 2565b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes } 2566b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes } 2567b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes} 2568b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes 2569eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young// Validate draw-time state related to the PSO 257051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool ValidatePipelineDrawtimeState(layer_data const *dev_data, LAST_BOUND_STATE const &state, const GLOBAL_CB_NODE *pCB, 25714c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis PIPELINE_STATE const *pPipeline) { 25723251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 257329d196e071b2dc1db47702085469396f2b956820Chris Forbes 2574d79335137b414d5f89284a9ab3e014beb4ada3ebMike Weiblen // Verify vertex binding 257529d196e071b2dc1db47702085469396f2b956820Chris Forbes if (pPipeline->vertexBindingDescriptions.size() > 0) { 257629d196e071b2dc1db47702085469396f2b956820Chris Forbes for (size_t i = 0; i < pPipeline->vertexBindingDescriptions.size(); i++) { 2577312129ec52e6249aa453e27e6be17a8dab1e98b8Tobin Ehlis auto vertex_binding = pPipeline->vertexBindingDescriptions[i].binding; 2578312129ec52e6249aa453e27e6be17a8dab1e98b8Tobin Ehlis if ((pCB->currentDrawData.buffers.size() < (vertex_binding + 1)) || 2579312129ec52e6249aa453e27e6be17a8dab1e98b8Tobin Ehlis (pCB->currentDrawData.buffers[vertex_binding] == VK_NULL_HANDLE)) { 25803251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 2581df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 2582df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(pCB->commandBuffer), __LINE__, DRAWSTATE_VTX_INDEX_OUT_OF_BOUNDS, "DS", 2583cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "The Pipeline State Object (0x%" PRIxLEAST64 2584cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ") expects that this Command Buffer's vertex binding Index %u " 2585cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "should be set via vkCmdBindVertexBuffers. This is because VkVertexInputBindingDescription struct " 2586cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "at index " PRINTF_SIZE_T_SPECIFIER " of pVertexBindingDescriptions has a binding value of %u.", 2587cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski (uint64_t)state.pipeline_state->pipeline, vertex_binding, i, vertex_binding); 258829d196e071b2dc1db47702085469396f2b956820Chris Forbes } 258929d196e071b2dc1db47702085469396f2b956820Chris Forbes } 259029d196e071b2dc1db47702085469396f2b956820Chris Forbes } else { 259158b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis if (!pCB->currentDrawData.buffers.empty() && !pCB->vertex_buffer_used) { 25923251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, 25933251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t>(pCB->commandBuffer), 25943251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski __LINE__, DRAWSTATE_VTX_INDEX_OUT_OF_BOUNDS, "DS", 25953251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Vertex buffers are bound to command buffer (0x%p" 25963251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski ") but no vertex buffers are attached to this Pipeline State Object (0x%" PRIxLEAST64 ").", 25973251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski pCB->commandBuffer, (uint64_t)state.pipeline_state->pipeline); 259829d196e071b2dc1db47702085469396f2b956820Chris Forbes } 259929d196e071b2dc1db47702085469396f2b956820Chris Forbes } 260029d196e071b2dc1db47702085469396f2b956820Chris Forbes // If Viewport or scissors are dynamic, verify that dynamic count matches PSO count. 260129d196e071b2dc1db47702085469396f2b956820Chris Forbes // Skip check if rasterization is disabled or there is no viewport. 260229d196e071b2dc1db47702085469396f2b956820Chris Forbes if ((!pPipeline->graphicsPipelineCI.pRasterizationState || 260329d196e071b2dc1db47702085469396f2b956820Chris Forbes (pPipeline->graphicsPipelineCI.pRasterizationState->rasterizerDiscardEnable == VK_FALSE)) && 260429d196e071b2dc1db47702085469396f2b956820Chris Forbes pPipeline->graphicsPipelineCI.pViewportState) { 260529d196e071b2dc1db47702085469396f2b956820Chris Forbes bool dynViewport = isDynamic(pPipeline, VK_DYNAMIC_STATE_VIEWPORT); 260629d196e071b2dc1db47702085469396f2b956820Chris Forbes bool dynScissor = isDynamic(pPipeline, VK_DYNAMIC_STATE_SCISSOR); 2607b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes 260829d196e071b2dc1db47702085469396f2b956820Chris Forbes if (dynViewport) { 2609b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes auto requiredViewportsMask = (1 << pPipeline->graphicsPipelineCI.pViewportState->viewportCount) - 1; 2610b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes auto missingViewportMask = ~pCB->viewportMask & requiredViewportsMask; 2611b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes if (missingViewportMask) { 2612b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes std::stringstream ss; 2613b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes ss << "Dynamic viewport(s) "; 2614b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes list_bits(ss, missingViewportMask); 2615d79335137b414d5f89284a9ab3e014beb4ada3ebMike Weiblen ss << " are used by pipeline state object, but were not provided via calls to vkCmdSetViewport()."; 26163251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 26173251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski __LINE__, DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS", "%s", ss.str().c_str()); 261829d196e071b2dc1db47702085469396f2b956820Chris Forbes } 261929d196e071b2dc1db47702085469396f2b956820Chris Forbes } 2620b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes 262129d196e071b2dc1db47702085469396f2b956820Chris Forbes if (dynScissor) { 2622b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes auto requiredScissorMask = (1 << pPipeline->graphicsPipelineCI.pViewportState->scissorCount) - 1; 2623b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes auto missingScissorMask = ~pCB->scissorMask & requiredScissorMask; 2624b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes if (missingScissorMask) { 2625b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes std::stringstream ss; 2626b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes ss << "Dynamic scissor(s) "; 2627b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes list_bits(ss, missingScissorMask); 2628d79335137b414d5f89284a9ab3e014beb4ada3ebMike Weiblen ss << " are used by pipeline state object, but were not provided via calls to vkCmdSetScissor()."; 26293251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 26303251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski __LINE__, DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS", "%s", ss.str().c_str()); 263129d196e071b2dc1db47702085469396f2b956820Chris Forbes } 263229d196e071b2dc1db47702085469396f2b956820Chris Forbes } 263329d196e071b2dc1db47702085469396f2b956820Chris Forbes } 263429d196e071b2dc1db47702085469396f2b956820Chris Forbes 263529d196e071b2dc1db47702085469396f2b956820Chris Forbes // Verify that any MSAA request in PSO matches sample# in bound FB 263629d196e071b2dc1db47702085469396f2b956820Chris Forbes // Skip the check if rasterization is disabled. 263729d196e071b2dc1db47702085469396f2b956820Chris Forbes if (!pPipeline->graphicsPipelineCI.pRasterizationState || 263829d196e071b2dc1db47702085469396f2b956820Chris Forbes (pPipeline->graphicsPipelineCI.pRasterizationState->rasterizerDiscardEnable == VK_FALSE)) { 263929d196e071b2dc1db47702085469396f2b956820Chris Forbes VkSampleCountFlagBits pso_num_samples = getNumSamples(pPipeline); 264029d196e071b2dc1db47702085469396f2b956820Chris Forbes if (pCB->activeRenderPass) { 2641fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes auto const render_pass_info = pCB->activeRenderPass->createInfo.ptr(); 264229d196e071b2dc1db47702085469396f2b956820Chris Forbes const VkSubpassDescription *subpass_desc = &render_pass_info->pSubpasses[pCB->activeSubpass]; 264329d196e071b2dc1db47702085469396f2b956820Chris Forbes uint32_t i; 264476957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes unsigned subpass_num_samples = 0; 26450a7ed0466d3d3c6c71be07d66c200482d9a9d073Chris Forbes 264629d196e071b2dc1db47702085469396f2b956820Chris Forbes for (i = 0; i < subpass_desc->colorAttachmentCount; i++) { 264776957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes auto attachment = subpass_desc->pColorAttachments[i].attachment; 264876957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes if (attachment != VK_ATTACHMENT_UNUSED) 264976957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes subpass_num_samples |= (unsigned)render_pass_info->pAttachments[attachment].samples; 265029d196e071b2dc1db47702085469396f2b956820Chris Forbes } 26510a7ed0466d3d3c6c71be07d66c200482d9a9d073Chris Forbes 265276957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes if (subpass_desc->pDepthStencilAttachment && 265376957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes subpass_desc->pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) { 265476957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes auto attachment = subpass_desc->pDepthStencilAttachment->attachment; 265576957dd352738b7ceec82c38be8b1b1347a90040Chris Forbes subpass_num_samples |= (unsigned)render_pass_info->pAttachments[attachment].samples; 265629d196e071b2dc1db47702085469396f2b956820Chris Forbes } 2657eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young 26580dc3fd4e57b8531638781daa01a2fb5d1048a6fbJamie Madill if (subpass_num_samples && static_cast<unsigned>(pso_num_samples) != subpass_num_samples) { 26593251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 26603251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<const uint64_t &>(pPipeline->pipeline), __LINE__, DRAWSTATE_NUM_SAMPLES_MISMATCH, 26613251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "DS", "Num samples mismatch! At draw-time in Pipeline (0x%" PRIxLEAST64 26623251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski ") with %u samples while current RenderPass (0x%" PRIxLEAST64 ") w/ %u samples!", 26633251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<const uint64_t &>(pPipeline->pipeline), pso_num_samples, 26643251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<const uint64_t &>(pCB->activeRenderPass->renderPass), subpass_num_samples); 2665eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young } 266629d196e071b2dc1db47702085469396f2b956820Chris Forbes } else { 26673251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 26683251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<const uint64_t &>(pPipeline->pipeline), __LINE__, DRAWSTATE_NUM_SAMPLES_MISMATCH, "DS", 26693251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "No active render pass found at draw-time in Pipeline (0x%" PRIxLEAST64 ")!", 26703251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<const uint64_t &>(pPipeline->pipeline)); 2671eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young } 2672eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young } 2673528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis // Verify that PSO creation renderPass is compatible with active renderPass 2674528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis if (pCB->activeRenderPass) { 2675528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis std::string err_string; 2676a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis if ((pCB->activeRenderPass->renderPass != pPipeline->graphicsPipelineCI.renderPass) && 267751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis !verify_renderpass_compatibility(dev_data, pCB->activeRenderPass->createInfo.ptr(), pPipeline->render_pass_ci.ptr(), 2678528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis err_string)) { 2679528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis // renderPass that PSO was created with must be compatible with active renderPass that PSO is being used with 26803251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 26813251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<const uint64_t &>(pPipeline->pipeline), __LINE__, DRAWSTATE_RENDERPASS_INCOMPATIBLE, 26823251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "DS", "At Draw time the active render pass (0x%" PRIxLEAST64 26833251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski ") is incompatible w/ gfx pipeline " 26843251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "(0x%" PRIxLEAST64 ") that was created w/ render pass (0x%" PRIxLEAST64 ") due to: %s", 26853251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t &>(pCB->activeRenderPass->renderPass), 26863251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t const &>(pPipeline->pipeline), 26873251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<const uint64_t &>(pPipeline->graphicsPipelineCI.renderPass), err_string.c_str()); 2688528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis } 2689c307df2953e6b023531a6ef7fd11e3ee2f2c58b0Chris Forbes 2690c307df2953e6b023531a6ef7fd11e3ee2f2c58b0Chris Forbes if (pPipeline->graphicsPipelineCI.subpass != pCB->activeSubpass) { 26913251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 26923251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t const &>(pPipeline->pipeline), __LINE__, DRAWSTATE_RENDERPASS_INCOMPATIBLE, 26933251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "DS", "Pipeline was built for subpass %u but used in subpass %u", pPipeline->graphicsPipelineCI.subpass, 26943251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski pCB->activeSubpass); 2695c307df2953e6b023531a6ef7fd11e3ee2f2c58b0Chris Forbes } 2696528f623d935b0ab102a2f9c1c82787a8810ca360Tobin Ehlis } 269729d196e071b2dc1db47702085469396f2b956820Chris Forbes // TODO : Add more checks here 269829d196e071b2dc1db47702085469396f2b956820Chris Forbes 26993251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 2700eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young} 2701eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young 27025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Validate overall state at the time of a draw call 270351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool ValidateDrawState(layer_data *dev_data, GLOBAL_CB_NODE *cb_node, const bool indexed, 27044f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes const VkPipelineBindPoint bind_point, const char *function, 27054f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes UNIQUE_VALIDATION_ERROR_CODE const msg_code) { 2706e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool result = false; 27071c130ea631a82716dc7334de17767536525f2292Tobin Ehlis auto const &state = cb_node->lastBound[bind_point]; 27084c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis PIPELINE_STATE *pPipe = state.pipeline_state; 270922fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis if (nullptr == pPipe) { 271022fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis result |= log_msg( 2711df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 2712df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, DRAWSTATE_INVALID_PIPELINE, "DS", 271322fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis "At Draw/Dispatch time no valid VkPipeline is bound! This is illegal. Please bind one with vkCmdBindPipeline()."); 271422fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis // Early return as any further checks below will be busted w/o a pipeline 2715cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (result) return true; 271622fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis } 27173d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis // First check flag states 27181c130ea631a82716dc7334de17767536525f2292Tobin Ehlis if (VK_PIPELINE_BIND_POINT_GRAPHICS == bind_point) 271951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis result = validate_draw_state_flags(dev_data, cb_node, pPipe, indexed, msg_code); 27207a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis 27215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Now complete other state checks 272269b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis if (VK_NULL_HANDLE != state.pipeline_layout.layout) { 272322fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis string errorString; 272469b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis auto pipeline_layout = pPipe->pipeline_layout; 2725169c4506062f06d6676eb4da3c9e0437d1d9d659Chris Forbes 27261c130ea631a82716dc7334de17767536525f2292Tobin Ehlis for (const auto &set_binding_pair : pPipe->active_slots) { 27271c130ea631a82716dc7334de17767536525f2292Tobin Ehlis uint32_t setIndex = set_binding_pair.first; 272822fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis // If valid set is not bound throw an error 272922fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis if ((state.boundDescriptorSets.size() <= setIndex) || (!state.boundDescriptorSets[setIndex])) { 2730df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski result |= log_msg( 2731df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 2732df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, DRAWSTATE_DESCRIPTOR_SET_NOT_BOUND, "DS", 2733df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "VkPipeline 0x%" PRIxLEAST64 " uses set #%u but that set is not bound.", (uint64_t)pPipe->pipeline, setIndex); 273412b7fc342b53fbdd399aae4a85959e37685936acChris Forbes } else if (!verify_set_layout_compatibility(state.boundDescriptorSets[setIndex], &pipeline_layout, setIndex, 273569b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis errorString)) { 273669b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis // Set is bound but not compatible w/ overlapping pipeline_layout from PSO 273771511c5a10533c910bfe62c3bcf58e2a4054e7acTobin Ehlis VkDescriptorSet setHandle = state.boundDescriptorSets[setIndex]->GetSet(); 273822fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis result |= 273951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, 274022fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis (uint64_t)setHandle, __LINE__, DRAWSTATE_PIPELINE_LAYOUTS_INCOMPATIBLE, "DS", 2741414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller "VkDescriptorSet (0x%" PRIxLEAST64 2742414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller ") bound as set #%u is not compatible with overlapping VkPipelineLayout 0x%" PRIxLEAST64 " due to: %s", 274369b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis reinterpret_cast<uint64_t &>(setHandle), setIndex, reinterpret_cast<uint64_t &>(pipeline_layout.layout), 274469b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis errorString.c_str()); 2745cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else { // Valid set is bound and layout compatible, validate that it's updated 274622fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis // Pull the set node 27471c130ea631a82716dc7334de17767536525f2292Tobin Ehlis cvdescriptorset::DescriptorSet *descriptor_set = state.boundDescriptorSets[setIndex]; 2748aa21bc3b3c5c7adfeb488fc80bdcb339d63615b8Tobin Ehlis // Gather active bindings 2749ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis std::unordered_set<uint32_t> active_bindings; 27501c130ea631a82716dc7334de17767536525f2292Tobin Ehlis for (auto binding : set_binding_pair.second) { 2751ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis active_bindings.insert(binding.first); 2752aa21bc3b3c5c7adfeb488fc80bdcb339d63615b8Tobin Ehlis } 275322fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis // Make sure set has been updated if it has no immutable samplers 275422fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis // If it has immutable samplers, we'll flag error later as needed depending on binding 27551c130ea631a82716dc7334de17767536525f2292Tobin Ehlis if (!descriptor_set->IsUpdated()) { 2756ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis for (auto binding : active_bindings) { 27571c130ea631a82716dc7334de17767536525f2292Tobin Ehlis if (!descriptor_set->GetImmutableSamplerPtrFromBinding(binding)) { 275851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis result |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 2759cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t)descriptor_set->GetSet(), 2760cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, DRAWSTATE_DESCRIPTOR_SET_NOT_UPDATED, "DS", 2761cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "Descriptor Set 0x%" PRIxLEAST64 2762cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " bound but was never updated. It is now being used to draw so " 2763cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "this will result in undefined behavior.", 2764cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski (uint64_t)descriptor_set->GetSet()); 2765fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis } 27665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 27675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 27687433ab60c7ff16d37edb0f8b17b606ccd363e210Tobin Ehlis // Validate the draw-time state for this descriptor set 27697433ab60c7ff16d37edb0f8b17b606ccd363e210Tobin Ehlis std::string err_str; 27700db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis if (!descriptor_set->ValidateDrawState(set_binding_pair.second, state.dynamicOffsets[setIndex], cb_node, function, 27710db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis &err_str)) { 27721c130ea631a82716dc7334de17767536525f2292Tobin Ehlis auto set = descriptor_set->GetSet(); 27730db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis result |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 27740db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, reinterpret_cast<const uint64_t &>(set), 27750db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis __LINE__, DRAWSTATE_DESCRIPTOR_SET_NOT_UPDATED, "DS", 27760db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis "Descriptor set 0x%" PRIxLEAST64 " encountered the following validation error at %s time: %s", 27770db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis reinterpret_cast<const uint64_t &>(set), function, err_str.c_str()); 27787433ab60c7ff16d37edb0f8b17b606ccd363e210Tobin Ehlis } 27795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 278022fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis } 278122fb3c0393ef588b11f8313f01c508028d77dec0Tobin Ehlis } 2782eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young 2783eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young // Check general pipeline state that needs to be validated at drawtime 278451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (VK_PIPELINE_BIND_POINT_GRAPHICS == bind_point) result |= ValidatePipelineDrawtimeState(dev_data, state, cb_node, pPipe); 2785eca2d52a6bfa3f9d63a86ca9fd30abc0adf775b7Mark Young 27865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 27875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 27885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 278951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic void UpdateDrawState(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, const VkPipelineBindPoint bind_point) { 27901c130ea631a82716dc7334de17767536525f2292Tobin Ehlis auto const &state = cb_state->lastBound[bind_point]; 2791ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis PIPELINE_STATE *pPipe = state.pipeline_state; 2792ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis if (VK_NULL_HANDLE != state.pipeline_layout.layout) { 27931c130ea631a82716dc7334de17767536525f2292Tobin Ehlis for (const auto &set_binding_pair : pPipe->active_slots) { 27941c130ea631a82716dc7334de17767536525f2292Tobin Ehlis uint32_t setIndex = set_binding_pair.first; 2795ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis // Pull the set node 27961c130ea631a82716dc7334de17767536525f2292Tobin Ehlis cvdescriptorset::DescriptorSet *descriptor_set = state.boundDescriptorSets[setIndex]; 2797ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis // Bind this set and its active descriptor resources to the command buffer 27981c130ea631a82716dc7334de17767536525f2292Tobin Ehlis descriptor_set->BindCommandBuffer(cb_state, set_binding_pair.second); 27997433ab60c7ff16d37edb0f8b17b606ccd363e210Tobin Ehlis // For given active slots record updated images & buffers 28001c130ea631a82716dc7334de17767536525f2292Tobin Ehlis descriptor_set->GetStorageUpdates(set_binding_pair.second, &cb_state->updateBuffers, &cb_state->updateImages); 2801ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis } 2802ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis } 280358b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis if (pPipe->vertexBindingDescriptions.size() > 0) { 280458b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis cb_state->vertex_buffer_used = true; 280558b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis } 2806ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis} 2807ec2ff49aea47929f28679d7bbe598ec439db7bb5Tobin Ehlis 2808a27508babf63d50aea75883a3702979193c23683Mark Young// Validate HW line width capabilities prior to setting requested line width. 280906727c7f56d1080aff506a9ae1ae9d8c174b3e9dMark Lobodzinskistatic bool verifyLineWidth(layer_data *dev_data, DRAW_STATE_ERROR dsError, VulkanObjectType object_type, const uint64_t &target, 281006727c7f56d1080aff506a9ae1ae9d8c174b3e9dMark Lobodzinski float lineWidth) { 28113251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 2812a27508babf63d50aea75883a3702979193c23683Mark Young 2813a27508babf63d50aea75883a3702979193c23683Mark Young // First check to see if the physical device supports wide lines. 281451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if ((VK_FALSE == dev_data->enabled_features.wideLines) && (1.0f != lineWidth)) { 28153251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, get_debug_report_enum[object_type], target, __LINE__, 28163251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski dsError, "DS", 28173251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Attempt to set lineWidth to %f but physical device wideLines feature " 28183251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "not supported/enabled so lineWidth must be 1.0f!", 28193251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski lineWidth); 2820a27508babf63d50aea75883a3702979193c23683Mark Young } else { 2821a27508babf63d50aea75883a3702979193c23683Mark Young // Otherwise, make sure the width falls in the valid range. 282251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if ((dev_data->phys_dev_properties.properties.limits.lineWidthRange[0] > lineWidth) || 282351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis (dev_data->phys_dev_properties.properties.limits.lineWidthRange[1] < lineWidth)) { 28243251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, get_debug_report_enum[object_type], target, 28253251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski __LINE__, dsError, "DS", 28263251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Attempt to set lineWidth to %f but physical device limits line width " 28273251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "to between [%f, %f]!", 28283251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski lineWidth, dev_data->phys_dev_properties.properties.limits.lineWidthRange[0], 28293251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski dev_data->phys_dev_properties.properties.limits.lineWidthRange[1]); 2830a27508babf63d50aea75883a3702979193c23683Mark Young } 2831a27508babf63d50aea75883a3702979193c23683Mark Young } 2832a27508babf63d50aea75883a3702979193c23683Mark Young 28333251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 2834a27508babf63d50aea75883a3702979193c23683Mark Young} 2835a27508babf63d50aea75883a3702979193c23683Mark Young 28365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Verify that create state for a pipeline is valid 283751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool verifyPipelineCreateState(layer_data *dev_data, std::vector<PIPELINE_STATE *> pPipelines, int pipelineIndex) { 28383251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 28395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 28404c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis PIPELINE_STATE *pPipeline = pPipelines[pipelineIndex]; 28415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 28425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // If create derivative bit is set, check that we've specified a base 28435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // pipeline correctly, and that the base pipeline was created to allow 28445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // derivatives. 28455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pPipeline->graphicsPipelineCI.flags & VK_PIPELINE_CREATE_DERIVATIVE_BIT) { 28464c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis PIPELINE_STATE *pBasePipeline = nullptr; 28475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!((pPipeline->graphicsPipelineCI.basePipelineHandle != VK_NULL_HANDLE) ^ 28485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (pPipeline->graphicsPipelineCI.basePipelineIndex != -1))) { 2849f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt // This check is a superset of VALIDATION_ERROR_00526 and VALIDATION_ERROR_00528 28503251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 28513251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t &>(pPipeline->pipeline), __LINE__, DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, 28523251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "DS", "Invalid Pipeline CreateInfo: exactly one of base pipeline index and handle must be specified"); 28535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (pPipeline->graphicsPipelineCI.basePipelineIndex != -1) { 28545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pPipeline->graphicsPipelineCI.basePipelineIndex >= pipelineIndex) { 28553251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 2856df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 2857df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t &>(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_00518, "DS", 2858f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt "Invalid Pipeline CreateInfo: base pipeline must occur earlier in array than derivative pipeline. %s", 2859f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt validation_error_map[VALIDATION_ERROR_00518]); 28605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 28615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pBasePipeline = pPipelines[pPipeline->graphicsPipelineCI.basePipelineIndex]; 28625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 28635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (pPipeline->graphicsPipelineCI.basePipelineHandle != VK_NULL_HANDLE) { 286451ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis pBasePipeline = getPipelineState(dev_data, pPipeline->graphicsPipelineCI.basePipelineHandle); 28655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 28665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 28675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pBasePipeline && !(pBasePipeline->graphicsPipelineCI.flags & VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT)) { 28683251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 28693251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t &>(pPipeline->pipeline), __LINE__, DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, 28703251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "DS", "Invalid Pipeline CreateInfo: base pipeline does not allow derivatives."); 28715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 28725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 28735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 28745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pPipeline->graphicsPipelineCI.pColorBlendState != NULL) { 2875fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis const safe_VkPipelineColorBlendStateCreateInfo *color_blend_state = pPipeline->graphicsPipelineCI.pColorBlendState; 28769a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto const render_pass_info = GetRenderPassState(dev_data, pPipeline->graphicsPipelineCI.renderPass)->createInfo.ptr(); 2877fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis const VkSubpassDescription *subpass_desc = &render_pass_info->pSubpasses[pPipeline->graphicsPipelineCI.subpass]; 2878fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis if (color_blend_state->attachmentCount != subpass_desc->colorAttachmentCount) { 28793251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg( 288051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 2881fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis reinterpret_cast<const uint64_t &>(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_02109, "DS", 2882fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis "vkCreateGraphicsPipelines(): Render pass (0x%" PRIxLEAST64 2883fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis ") subpass %u has colorAttachmentCount of %u which doesn't match the pColorBlendState->attachmentCount of %u. %s", 2884fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis reinterpret_cast<const uint64_t &>(pPipeline->graphicsPipelineCI.renderPass), pPipeline->graphicsPipelineCI.subpass, 2885fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis subpass_desc->colorAttachmentCount, color_blend_state->attachmentCount, 2886fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis validation_error_map[VALIDATION_ERROR_02109]); 2887fb4e70f35eef785ce77fca908d4d64f60539893dTobin Ehlis } 288851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (!dev_data->enabled_features.independentBlend) { 28893d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis if (pPipeline->attachments.size() > 1) { 289026c548826ff0f83d12c769b51e7d6f76d1265c0eChris Forbes VkPipelineColorBlendAttachmentState *pAttachments = &pPipeline->attachments[0]; 2891c7bd67f06427b08ba65cdf2dd529c8234beebdd5Mark Lobodzinski for (size_t i = 1; i < pPipeline->attachments.size(); i++) { 289206811df0256552cd7da9d7297672af377463fc4aMark Mueller // Quoting the spec: "If [the independent blend] feature is not enabled, the VkPipelineColorBlendAttachmentState 289306811df0256552cd7da9d7297672af377463fc4aMark Mueller // settings for all color attachments must be identical." VkPipelineColorBlendAttachmentState contains 289406811df0256552cd7da9d7297672af377463fc4aMark Mueller // only attachment state, so memcmp is best suited for the comparison 289506811df0256552cd7da9d7297672af377463fc4aMark Mueller if (memcmp(static_cast<const void *>(pAttachments), static_cast<const void *>(&pAttachments[i]), 289606811df0256552cd7da9d7297672af377463fc4aMark Mueller sizeof(pAttachments[0]))) { 28973251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 2898df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 2899df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t &>(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_01532, "DS", 2900df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "Invalid Pipeline CreateInfo: If independent blend feature not " 2901df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "enabled, all elements of pAttachments must be identical. %s", 2902df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski validation_error_map[VALIDATION_ERROR_01532]); 290306811df0256552cd7da9d7297672af377463fc4aMark Mueller break; 2904c7bd67f06427b08ba65cdf2dd529c8234beebdd5Mark Lobodzinski } 29055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 29065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 29075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 290851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (!dev_data->enabled_features.logicOp && (pPipeline->graphicsPipelineCI.pColorBlendState->logicOpEnable != VK_FALSE)) { 29093251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 2910df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 2911df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t &>(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_01533, "DS", 2912f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt "Invalid Pipeline CreateInfo: If logic operations feature not enabled, logicOpEnable must be VK_FALSE. %s", 2913f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt validation_error_map[VALIDATION_ERROR_01533]); 29145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 29155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 29165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 2917a61b537fcb6a4f7b92cd217b3964ad7a48109da1Tobin Ehlis // Ensure the subpass index is valid. If not, then validate_and_capture_pipeline_shader_state 29185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // produces nonsense errors that confuse users. Other layers should already 29195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // emit errors for renderpass being invalid. 29209a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto renderPass = GetRenderPassState(dev_data, pPipeline->graphicsPipelineCI.renderPass); 2921fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes if (renderPass && pPipeline->graphicsPipelineCI.subpass >= renderPass->createInfo.subpassCount) { 29223251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 29233251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t &>(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_02122, "DS", 29243251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Invalid Pipeline CreateInfo State: Subpass index %u " 29253251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "is out of range for this renderpass (0..%u). %s", 29263251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski pPipeline->graphicsPipelineCI.subpass, renderPass->createInfo.subpassCount - 1, 29273251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski validation_error_map[VALIDATION_ERROR_02122]); 29285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 29295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 29301b52022446fb65466dfcee491393670ac12aaa33Chris Forbes if (!GetDisables(dev_data)->shader_validation && validate_and_capture_pipeline_shader_state(dev_data, pPipeline)) { 29313251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip = true; 29325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 293352156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes // Each shader's stage must be unique 293452156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes if (pPipeline->duplicate_shaders) { 293552156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes for (uint32_t stage = VK_SHADER_STAGE_VERTEX_BIT; stage & VK_SHADER_STAGE_ALL_GRAPHICS; stage <<= 1) { 293652156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes if (pPipeline->duplicate_shaders & stage) { 29373251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 2938df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 2939df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t &>(pPipeline->pipeline), __LINE__, DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, 2940df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "DS", "Invalid Pipeline CreateInfo State: Multiple shaders provided for stage %s", 2941df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski string_VkShaderStageFlagBits(VkShaderStageFlagBits(stage))); 294252156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes } 294352156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes } 294452156ec29c88c0e52eb89fb42867adacb1dd31bbChris Forbes } 29455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // VS is required 29465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!(pPipeline->active_shaders & VK_SHADER_STAGE_VERTEX_BIT)) { 29473251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 2948df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 2949df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t &>(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_00532, "DS", 2950df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "Invalid Pipeline CreateInfo State: Vertex Shader required. %s", validation_error_map[VALIDATION_ERROR_00532]); 29515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 29525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Either both or neither TC/TE shaders should be defined 2953f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt if ((pPipeline->active_shaders & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) && 2954f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt !(pPipeline->active_shaders & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)) { 29553251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 29563251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t &>(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_00534, "DS", 29573251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Invalid Pipeline CreateInfo State: TE and TC shaders must be included or excluded as a pair. %s", 29583251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski validation_error_map[VALIDATION_ERROR_00534]); 2959f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt } 2960f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt if (!(pPipeline->active_shaders & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) && 2961f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt (pPipeline->active_shaders & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)) { 29623251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 29633251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t &>(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_00535, "DS", 29643251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Invalid Pipeline CreateInfo State: TE and TC shaders must be included or excluded as a pair. %s", 29653251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski validation_error_map[VALIDATION_ERROR_00535]); 29665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 29675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Compute shaders should be specified independent of Gfx shaders 2968f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt if (pPipeline->active_shaders & VK_SHADER_STAGE_COMPUTE_BIT) { 29693251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 29703251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t &>(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_00533, "DS", 29713251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Invalid Pipeline CreateInfo State: Do not specify Compute Shader for Gfx Pipeline. %s", 29723251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski validation_error_map[VALIDATION_ERROR_00533]); 29735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 29745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // VK_PRIMITIVE_TOPOLOGY_PATCH_LIST primitive topology is only valid for tessellation pipelines. 29755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Mismatching primitive topology and tessellation fails graphics pipeline creation. 29765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pPipeline->active_shaders & (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) && 2977ca546210846c65808717f8875deae39bd227c240Tobin Ehlis (!pPipeline->graphicsPipelineCI.pInputAssemblyState || 2978ca546210846c65808717f8875deae39bd227c240Tobin Ehlis pPipeline->graphicsPipelineCI.pInputAssemblyState->topology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST)) { 29793251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 29803251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t &>(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_02099, "DS", 29813251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Invalid Pipeline CreateInfo State: " 29823251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "VK_PRIMITIVE_TOPOLOGY_PATCH_LIST must be set as IA " 29833251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "topology for tessellation pipelines. %s", 29843251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski validation_error_map[VALIDATION_ERROR_02099]); 29855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 2986ca546210846c65808717f8875deae39bd227c240Tobin Ehlis if (pPipeline->graphicsPipelineCI.pInputAssemblyState && 2987ca546210846c65808717f8875deae39bd227c240Tobin Ehlis pPipeline->graphicsPipelineCI.pInputAssemblyState->topology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST) { 29885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (~pPipeline->active_shaders & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) { 29893251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 29903251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t &>(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_02100, "DS", 29913251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Invalid Pipeline CreateInfo State: " 29923251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "VK_PRIMITIVE_TOPOLOGY_PATCH_LIST primitive " 29933251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "topology is only valid for tessellation pipelines. %s", 29943251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski validation_error_map[VALIDATION_ERROR_02100]); 29955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 29965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 2997f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt 2998f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt if (pPipeline->graphicsPipelineCI.pTessellationState && 2999f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt ((pPipeline->graphicsPipelineCI.pTessellationState->patchControlPoints == 0) || 3000f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt (pPipeline->graphicsPipelineCI.pTessellationState->patchControlPoints > 300151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->phys_dev_properties.properties.limits.maxTessellationPatchSize))) { 30023251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 30033251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t &>(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_01426, "DS", 30043251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Invalid Pipeline CreateInfo State: " 30053251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "VK_PRIMITIVE_TOPOLOGY_PATCH_LIST primitive " 30063251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "topology used with patchControlPoints value %u." 30073251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski " patchControlPoints should be >0 and <=%u. %s", 30083251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski pPipeline->graphicsPipelineCI.pTessellationState->patchControlPoints, 30093251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski dev_data->phys_dev_properties.properties.limits.maxTessellationPatchSize, 30103251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski validation_error_map[VALIDATION_ERROR_01426]); 3011f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt } 3012f62c50f00d7d03e27fbc3769e582761e8a4944ddMike Schuchardt 30136b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen // If a rasterization state is provided... 3014a27508babf63d50aea75883a3702979193c23683Mark Young if (pPipeline->graphicsPipelineCI.pRasterizationState) { 30156b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen // Make sure that the line width conforms to the HW. 3016a27508babf63d50aea75883a3702979193c23683Mark Young if (!isDynamic(pPipeline, VK_DYNAMIC_STATE_LINE_WIDTH)) { 30173251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= verifyLineWidth(dev_data, DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, kVulkanObjectTypePipeline, 30183251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t const &>(pPipeline->pipeline), 30193251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski pPipeline->graphicsPipelineCI.pRasterizationState->lineWidth); 3020a27508babf63d50aea75883a3702979193c23683Mark Young } 30215dcdd90e54199dfeb29938a3a03d998397c22664Chris Forbes 302258c5552c73679f81f57a64a809f7d4d6d52f4ce3Mark Lobodzinski if ((pPipeline->graphicsPipelineCI.pRasterizationState->depthClampEnable == VK_TRUE) && 302358c5552c73679f81f57a64a809f7d4d6d52f4ce3Mark Lobodzinski (!dev_data->enabled_features.depthClamp)) { 30243251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 30253251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t &>(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_01455, "DS", 30263251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkCreateGraphicsPipelines(): the depthClamp device feature is disabled: the depthClampEnable " 30273251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "member of the VkPipelineRasterizationStateCreateInfo structure must be set to VK_FALSE. %s", 30283251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski validation_error_map[VALIDATION_ERROR_01455]); 302958c5552c73679f81f57a64a809f7d4d6d52f4ce3Mark Lobodzinski } 303058c5552c73679f81f57a64a809f7d4d6d52f4ce3Mark Lobodzinski 3031434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski if (!isDynamic(pPipeline, VK_DYNAMIC_STATE_DEPTH_BIAS) && 3032434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski (pPipeline->graphicsPipelineCI.pRasterizationState->depthBiasClamp != 0.0) && 3033434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski (!dev_data->enabled_features.depthBiasClamp)) { 30343251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 30353251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t &>(pPipeline->pipeline), __LINE__, DRAWSTATE_INVALID_FEATURE, "DS", 30363251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkCreateGraphicsPipelines(): the depthBiasClamp device feature is disabled: the depthBiasClamp " 30373251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "member of the VkPipelineRasterizationStateCreateInfo structure must be set to 0.0 unless the " 30383251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "VK_DYNAMIC_STATE_DEPTH_BIAS dynamic state is enabled"); 3039434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski } 3040434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski 30416b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen // If rasterization is enabled... 30426b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen if (pPipeline->graphicsPipelineCI.pRasterizationState->rasterizerDiscardEnable == VK_FALSE) { 30436b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen auto subpass_desc = renderPass ? &renderPass->createInfo.pSubpasses[pPipeline->graphicsPipelineCI.subpass] : nullptr; 30446b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen 3045148e8028deee2b4b00ccd4a69210897add328265Mark Lobodzinski if ((pPipeline->graphicsPipelineCI.pMultisampleState->alphaToOneEnable == VK_TRUE) && 3046148e8028deee2b4b00ccd4a69210897add328265Mark Lobodzinski (!dev_data->enabled_features.alphaToOne)) { 30473251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 30483251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t &>(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_01464, "DS", 30493251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkCreateGraphicsPipelines(): the alphaToOne device feature is disabled: the alphaToOneEnable " 30503251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "member of the VkPipelineMultisampleStateCreateInfo structure must be set to VK_FALSE. %s", 30513251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski validation_error_map[VALIDATION_ERROR_01464]); 3052148e8028deee2b4b00ccd4a69210897add328265Mark Lobodzinski } 3053148e8028deee2b4b00ccd4a69210897add328265Mark Lobodzinski 30546b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen // If subpass uses a depth/stencil attachment, pDepthStencilState must be a pointer to a valid structure 30556b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen if (subpass_desc && subpass_desc->pDepthStencilAttachment && 30566b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen subpass_desc->pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) { 30576b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen if (!pPipeline->graphicsPipelineCI.pDepthStencilState) { 30583251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 30593251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t &>(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_02115, "DS", 30603251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Invalid Pipeline CreateInfo State: pDepthStencilState is NULL when rasterization is " 30613251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "enabled and subpass uses a depth/stencil attachment. %s", 30623251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski validation_error_map[VALIDATION_ERROR_02115]); 30639580629edfc5154cc9e36974cca12966fbd748b9Mark Lobodzinski 30649580629edfc5154cc9e36974cca12966fbd748b9Mark Lobodzinski } else if ((pPipeline->graphicsPipelineCI.pDepthStencilState->depthBoundsTestEnable == VK_TRUE) && 30659580629edfc5154cc9e36974cca12966fbd748b9Mark Lobodzinski (!dev_data->enabled_features.depthBounds)) { 30663251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg( 3067df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 3068df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t &>(pPipeline->pipeline), __LINE__, DRAWSTATE_INVALID_FEATURE, "DS", 30699580629edfc5154cc9e36974cca12966fbd748b9Mark Lobodzinski "vkCreateGraphicsPipelines(): the depthBounds device feature is disabled: the depthBoundsTestEnable " 30709580629edfc5154cc9e36974cca12966fbd748b9Mark Lobodzinski "member of the VkPipelineDepthStencilStateCreateInfo structure must be set to VK_FALSE."); 30716b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen } 30725dcdd90e54199dfeb29938a3a03d998397c22664Chris Forbes } 3073326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen 3074326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen // If subpass uses color attachments, pColorBlendState must be valid pointer 3075326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen if (subpass_desc) { 3076326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen uint32_t color_attachment_count = 0; 3077326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen for (uint32_t i = 0; i < subpass_desc->colorAttachmentCount; ++i) { 3078326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen if (subpass_desc->pColorAttachments[i].attachment != VK_ATTACHMENT_UNUSED) { 3079326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen ++color_attachment_count; 3080326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen } 3081326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen } 3082326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen if (color_attachment_count > 0 && pPipeline->graphicsPipelineCI.pColorBlendState == nullptr) { 30833251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 30843251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t &>(pPipeline->pipeline), __LINE__, VALIDATION_ERROR_02116, "DS", 30853251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Invalid Pipeline CreateInfo State: pColorBlendState is NULL when rasterization is " 30863251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "enabled and subpass uses color attachments. %s", 30873251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski validation_error_map[VALIDATION_ERROR_02116]); 3088326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen } 3089326fc9f00659303e0a5b3fc4019db2bda641c7bdMike Weiblen } 30905dcdd90e54199dfeb29938a3a03d998397c22664Chris Forbes } 30915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 30926b8d2b83e8400e5238705a0856b5e3acff8df742Mike Weiblen 30933251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 30945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 30955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 30965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Free the Pipeline nodes 309751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic void deletePipelines(layer_data *dev_data) { 309851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (dev_data->pipelineMap.size() <= 0) return; 309951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis for (auto &pipe_map_pair : dev_data->pipelineMap) { 3100ca546210846c65808717f8875deae39bd227c240Tobin Ehlis delete pipe_map_pair.second; 31015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 310251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->pipelineMap.clear(); 31035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 31045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 31055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Block of code at start here specifically for managing/tracking DSs 31065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 31075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Return Pool node ptr for specified pool or else NULL 31089a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisDESCRIPTOR_POOL_STATE *GetDescriptorPoolState(const layer_data *dev_data, const VkDescriptorPool pool) { 3109bb7ea477706f90eb2a72887f652795bc79f60ddeTobin Ehlis auto pool_it = dev_data->descriptorPoolMap.find(pool); 3110bb7ea477706f90eb2a72887f652795bc79f60ddeTobin Ehlis if (pool_it == dev_data->descriptorPoolMap.end()) { 31115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return NULL; 31125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 3113bb7ea477706f90eb2a72887f652795bc79f60ddeTobin Ehlis return pool_it->second; 31145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 31155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 31165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Validate that given set is valid and that it's not being used by an in-flight CmdBuffer 31175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// func_str is the name of the calling function 3118e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves// Return false if no errors occur 3119e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves// Return true if validation error occurs and callback returns true (to skip upcoming API call down the chain) 31200dcd0f7b37456e2e552d37094ba503c0d089b906Tobin Ehlisstatic bool validateIdleDescriptorSet(const layer_data *dev_data, VkDescriptorSet set, std::string func_str) { 3121cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.idle_descriptor_set) return false; 31223251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 31230dcd0f7b37456e2e552d37094ba503c0d089b906Tobin Ehlis auto set_node = dev_data->setMap.find(set); 31240dcd0f7b37456e2e552d37094ba503c0d089b906Tobin Ehlis if (set_node == dev_data->setMap.end()) { 31253251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, 31263251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski (uint64_t)(set), __LINE__, DRAWSTATE_DOUBLE_DESTROY, "DS", 31273251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Cannot call %s() on descriptor set 0x%" PRIxLEAST64 " that has not been allocated.", func_str.c_str(), 31283251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski (uint64_t)(set)); 31295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 31301c48e214b2ed50690da7f42f2013be3a6ef267dfTobin Ehlis // TODO : This covers various error cases so should pass error enum into this function and use passed in enum here 31315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (set_node->second->in_use.load()) { 31323251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, 31333251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski (uint64_t)(set), __LINE__, VALIDATION_ERROR_00919, "DS", 31343251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Cannot call %s() on descriptor set 0x%" PRIxLEAST64 " that is in use by a command buffer. %s", 31353251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski func_str.c_str(), (uint64_t)(set), validation_error_map[VALIDATION_ERROR_00919]); 31365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 31375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 31383251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 31395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 3140f80bf38f4fb3f177b3e1be11b7b1c5edcdbf7d9bChris Forbes 3141e6651096ed8f07840447783c66827cc16d659a49Tobin Ehlis// Remove set from setMap and delete the set 31429dd448578d59cb5ce692e833ba230783b30f3550Tobin Ehlisstatic void freeDescriptorSet(layer_data *dev_data, cvdescriptorset::DescriptorSet *descriptor_set) { 31439dd448578d59cb5ce692e833ba230783b30f3550Tobin Ehlis dev_data->setMap.erase(descriptor_set->GetSet()); 31449dd448578d59cb5ce692e833ba230783b30f3550Tobin Ehlis delete descriptor_set; 31459dd448578d59cb5ce692e833ba230783b30f3550Tobin Ehlis} 31465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Free all DS Pools including their Sets & related sub-structs 31475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// NOTE : Calls to this function should be wrapped in mutex 314851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic void deletePools(layer_data *dev_data) { 314951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (dev_data->descriptorPoolMap.size() <= 0) return; 315051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis for (auto ii = dev_data->descriptorPoolMap.begin(); ii != dev_data->descriptorPoolMap.end(); ++ii) { 3151c5f47f0a54e14c47d402aeabc6498d981ecda9ccTobin Ehlis // Remove this pools' sets from setMap and delete them 3152cb9ce9e05b8e939d3da35c64997c70049877f4feTobin Ehlis for (auto ds : (*ii).second->sets) { 315351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis freeDescriptorSet(dev_data, ds); 31545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 3155f13bee0887f3c3d1d597c82869864be3be836737Tobin Ehlis (*ii).second->sets.clear(); 31565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 315751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->descriptorPoolMap.clear(); 31585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 31595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 316051ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic void clearDescriptorPool(layer_data *dev_data, const VkDevice device, const VkDescriptorPool pool, 31615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkDescriptorPoolResetFlags flags) { 31629a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DESCRIPTOR_POOL_STATE *pPool = GetDescriptorPoolState(dev_data, pool); 3163de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis // TODO: validate flags 3164de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis // For every set off of this pool, clear it, remove from setMap, and free cvdescriptorset::DescriptorSet 3165de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis for (auto ds : pPool->sets) { 316651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis freeDescriptorSet(dev_data, ds); 3167de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis } 3168de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis pPool->sets.clear(); 3169de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis // Reset available count for each type and available sets for this pool 3170de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis for (uint32_t i = 0; i < pPool->availableDescriptorTypeCount.size(); ++i) { 3171de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis pPool->availableDescriptorTypeCount[i] = pPool->maxDescriptorTypeCount[i]; 31725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 3173de7672b6b749c09c5991bd8038b3a35ef82a69dcTobin Ehlis pPool->availableSets = pPool->maxSets; 31745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 31755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 31765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// For given CB object, fetch associated CB Node from map 31779a9a0db2a973034d4286b6d4c62a46beb7641791Tobin EhlisGLOBAL_CB_NODE *GetCBNode(layer_data const *dev_data, const VkCommandBuffer cb) { 317851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis auto it = dev_data->commandBufferMap.find(cb); 317951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (it == dev_data->commandBufferMap.end()) { 31805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return NULL; 31815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 31825121a8dcacb23766ba4455b4eea429f0a3d62099Chris Forbes return it->second; 31835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 31845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 318529f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis// If a renderpass is active, verify that the given command type is appropriate for current subpass state 318629f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlisbool ValidateCmdSubpassState(const layer_data *dev_data, const GLOBAL_CB_NODE *pCB, const CMD_TYPE cmd_type) { 3187cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!pCB->activeRenderPass) return false; 31883251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 3189d0d8e333806eaac08bdc87ddeff886dc2b0f09e7Tobin Ehlis if (pCB->activeSubpassContents == VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS && 3190d0d8e333806eaac08bdc87ddeff886dc2b0f09e7Tobin Ehlis (cmd_type != CMD_EXECUTECOMMANDS && cmd_type != CMD_NEXTSUBPASS && cmd_type != CMD_ENDRENDERPASS)) { 31913251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 31923251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t>(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER, "DS", 31933251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Commands cannot be called in a subpass using secondary command buffers."); 31945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (pCB->activeSubpassContents == VK_SUBPASS_CONTENTS_INLINE && cmd_type == CMD_EXECUTECOMMANDS) { 31953251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 31963251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t>(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER, "DS", 31973251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkCmdExecuteCommands() cannot be called in a subpass using inline commands."); 31985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 31993251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 32005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 32015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3202baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardtbool ValidateCmdQueueFlags(layer_data *dev_data, GLOBAL_CB_NODE *cb_node, const char *caller_name, VkQueueFlags required_flags, 3203baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt UNIQUE_VALIDATION_ERROR_CODE error_code) { 3204baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt auto pool = GetCommandPoolNode(dev_data, cb_node->createInfo.commandPool); 3205baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt if (pool) { 3206baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt VkQueueFlags queue_flags = dev_data->phys_dev_properties.queue_family_properties[pool->queueFamilyIndex].queueFlags; 3207baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt if (!(required_flags & queue_flags)) { 3208baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt string required_flags_string; 3209baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt for (auto flag : {VK_QUEUE_TRANSFER_BIT, VK_QUEUE_GRAPHICS_BIT, VK_QUEUE_COMPUTE_BIT}) { 3210baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt if (flag & required_flags) { 3211baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt if (required_flags_string.size()) { 3212baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt required_flags_string += " or "; 3213baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt } 3214baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt required_flags_string += string_VkQueueFlagBits(flag); 3215baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt } 3216baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt } 3217baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt return log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 3218baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt reinterpret_cast<uint64_t>(cb_node->commandBuffer), __LINE__, error_code, "DS", 3219baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt "Cannot call %s on a command buffer allocated from a pool without %s capabilities. %s.", caller_name, 3220baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt required_flags_string.c_str(), validation_error_map[error_code]); 3221baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt } 3222baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt } 32235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return false; 32245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 32255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3226ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinskistatic bool ReportInvalidCommandBuffer(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, const char *call_source) { 3227ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski bool skip = false; 3228ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski for (auto obj : cb_state->broken_bindings) { 32297a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski const char *type_str = object_string[obj.type]; 3230ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski // Descriptor sets are a special case that can be either destroyed or updated to invalidate a CB 32317a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski const char *cause_str = (obj.type == kVulkanObjectTypeDescriptorSet) ? "destroyed or updated" : "destroyed"; 3232ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 3233ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski reinterpret_cast<uint64_t &>(cb_state->commandBuffer), __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER, "DS", 3234ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski "You are adding %s to command buffer 0x%p that is invalid because bound %s 0x%" PRIxLEAST64 " was %s.", 3235ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski call_source, cb_state->commandBuffer, type_str, obj.handle, cause_str); 3236ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } 3237ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski return skip; 3238ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski} 3239ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski 3240623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski// Validate the given command being added to the specified cmd buffer, flagging errors if CB is not in the recording state or if 3241623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski// there's an issue with the Cmd ordering 3242946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinskibool ValidateCmd(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, const CMD_TYPE cmd, const char *caller_name) { 324333f3623e8124c3a6081b60f68b9d39a19a5840aeChris Forbes switch (cb_state->state) { 324433f3623e8124c3a6081b60f68b9d39a19a5840aeChris Forbes case CB_RECORDING: 324533f3623e8124c3a6081b60f68b9d39a19a5840aeChris Forbes return ValidateCmdSubpassState(dev_data, cb_state, cmd); 324633f3623e8124c3a6081b60f68b9d39a19a5840aeChris Forbes 324733f3623e8124c3a6081b60f68b9d39a19a5840aeChris Forbes case CB_INVALID: 324833f3623e8124c3a6081b60f68b9d39a19a5840aeChris Forbes return ReportInvalidCommandBuffer(dev_data, cb_state, caller_name); 324933f3623e8124c3a6081b60f68b9d39a19a5840aeChris Forbes 325033f3623e8124c3a6081b60f68b9d39a19a5840aeChris Forbes default: 325133f3623e8124c3a6081b60f68b9d39a19a5840aeChris Forbes return log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 325233f3623e8124c3a6081b60f68b9d39a19a5840aeChris Forbes reinterpret_cast<uint64_t &>(cb_state->commandBuffer), __LINE__, DRAWSTATE_NO_BEGIN_COMMAND_BUFFER, "DS", 325333f3623e8124c3a6081b60f68b9d39a19a5840aeChris Forbes "You must call vkBeginCommandBuffer() before this call to %s", caller_name); 32545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 32555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 325629f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis 32571ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlisvoid UpdateCmdBufferLastCmd(GLOBAL_CB_NODE *cb_state, const CMD_TYPE cmd) { 325829f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis if (cb_state->state == CB_RECORDING) { 325929f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis cb_state->last_cmd = cmd; 326029f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis } 326129f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis} 32627e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis// For given object struct return a ptr of BASE_NODE type for its wrapping struct 32637e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin EhlisBASE_NODE *GetStateStructPtrFromObject(layer_data *dev_data, VK_OBJECT object_struct) { 32647e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis BASE_NODE *base_ptr = nullptr; 32657e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis switch (object_struct.type) { 3266ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes case kVulkanObjectTypeDescriptorSet: { 32679a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetSetNode(dev_data, reinterpret_cast<VkDescriptorSet &>(object_struct.handle)); 3268cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3269cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3270ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes case kVulkanObjectTypeSampler: { 32719a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetSamplerState(dev_data, reinterpret_cast<VkSampler &>(object_struct.handle)); 3272cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3273cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3274ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes case kVulkanObjectTypeQueryPool: { 32759a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetQueryPoolNode(dev_data, reinterpret_cast<VkQueryPool &>(object_struct.handle)); 3276cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3277cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3278ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes case kVulkanObjectTypePipeline: { 3279cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski base_ptr = getPipelineState(dev_data, reinterpret_cast<VkPipeline &>(object_struct.handle)); 3280cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3281cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3282ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes case kVulkanObjectTypeBuffer: { 32839a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetBufferState(dev_data, reinterpret_cast<VkBuffer &>(object_struct.handle)); 3284cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3285cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3286ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes case kVulkanObjectTypeBufferView: { 32879a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetBufferViewState(dev_data, reinterpret_cast<VkBufferView &>(object_struct.handle)); 3288cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3289cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3290ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes case kVulkanObjectTypeImage: { 32919a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetImageState(dev_data, reinterpret_cast<VkImage &>(object_struct.handle)); 3292cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3293cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3294ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes case kVulkanObjectTypeImageView: { 32959a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetImageViewState(dev_data, reinterpret_cast<VkImageView &>(object_struct.handle)); 3296cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3297cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3298ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes case kVulkanObjectTypeEvent: { 32999a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetEventNode(dev_data, reinterpret_cast<VkEvent &>(object_struct.handle)); 3300cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3301cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3302ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes case kVulkanObjectTypeDescriptorPool: { 33039a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetDescriptorPoolState(dev_data, reinterpret_cast<VkDescriptorPool &>(object_struct.handle)); 3304cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3305cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3306ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes case kVulkanObjectTypeCommandPool: { 33079a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetCommandPoolNode(dev_data, reinterpret_cast<VkCommandPool &>(object_struct.handle)); 3308cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3309cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3310ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes case kVulkanObjectTypeFramebuffer: { 33119a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetFramebufferState(dev_data, reinterpret_cast<VkFramebuffer &>(object_struct.handle)); 3312cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3313cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3314ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes case kVulkanObjectTypeRenderPass: { 33159a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetRenderPassState(dev_data, reinterpret_cast<VkRenderPass &>(object_struct.handle)); 3316cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3317cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3318ed832a346f5de647635da80bcdb95e29634c70d2Chris Forbes case kVulkanObjectTypeDeviceMemory: { 33199a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis base_ptr = GetMemObjInfo(dev_data, reinterpret_cast<VkDeviceMemory &>(object_struct.handle)); 3320cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3321cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 3322cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 3323cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // TODO : Any other objects to be handled here? 3324cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski assert(0); 3325cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3326bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis } 33277e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis return base_ptr; 33287e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis} 33297e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis 33307e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis// Tie the VK_OBJECT to the cmd buffer which includes: 33317e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis// Add object_binding to cmd buffer 33327e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis// Add cb_binding to object 33337e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlisstatic void addCommandBufferBinding(std::unordered_set<GLOBAL_CB_NODE *> *cb_bindings, VK_OBJECT obj, GLOBAL_CB_NODE *cb_node) { 33347e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis cb_bindings->insert(cb_node); 33357e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis cb_node->object_bindings.insert(obj); 33367e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis} 33377e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis// For a given object, if cb_node is in that objects cb_bindings, remove cb_node 33387e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlisstatic void removeCommandBufferBinding(layer_data *dev_data, VK_OBJECT const *object, GLOBAL_CB_NODE *cb_node) { 33397e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis BASE_NODE *base_obj = GetStateStructPtrFromObject(dev_data, *object); 3340cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (base_obj) base_obj->cb_bindings.erase(cb_node); 3341bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis} 33425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Reset the command buffer state 33435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Maintain the createInfo and set state to CB_NEW, but clear all other state 3344400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlisstatic void resetCB(layer_data *dev_data, const VkCommandBuffer cb) { 3345400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis GLOBAL_CB_NODE *pCB = dev_data->commandBufferMap[cb]; 33465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 3347b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine pCB->in_use.store(0); 3348347d4d3139a1e743ed85bd375c20fd35bbe68d74Chris Forbes pCB->last_cmd = CMD_NONE; 33495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Reset CB state (note that createInfo is not cleared) 33505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->commandBuffer = cb; 33515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis memset(&pCB->beginInfo, 0, sizeof(VkCommandBufferBeginInfo)); 33525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis memset(&pCB->inheritanceInfo, 0, sizeof(VkCommandBufferInheritanceInfo)); 3353b68b13ed4952bce61f6ebb0023542660c26b0562Chris Forbes pCB->hasDrawCmd = false; 33545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->state = CB_NEW; 33555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->submitCount = 0; 33565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->status = 0; 3357b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes pCB->viewportMask = 0; 3358b0df98f4fa837a06691c1e3c05b4ed21c7e2d014Chris Forbes pCB->scissorMask = 0; 335993c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski 336072d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis for (uint32_t i = 0; i < VK_PIPELINE_BIND_POINT_RANGE_SIZE; ++i) { 336172d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis pCB->lastBound[i].reset(); 336272d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis } 336393c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski 33645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis memset(&pCB->activeRenderPassBeginInfo, 0, sizeof(pCB->activeRenderPassBeginInfo)); 3365ee691f5c5fa87aac3750454d2bca2cb582e4e817Chris Forbes pCB->activeRenderPass = nullptr; 33665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->activeSubpassContents = VK_SUBPASS_CONTENTS_INLINE; 33675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->activeSubpass = 0; 3368e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis pCB->broken_bindings.clear(); 33695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->waitedEvents.clear(); 33705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->events.clear(); 3371c7e6bc41aa9c6e5a677b138b9459b252cd3bedf2Mark Lobodzinski pCB->writeEventsBeforeWait.clear(); 33725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->waitedEventsBeforeQueryReset.clear(); 33735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->queryToStateMap.clear(); 33745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->activeQueries.clear(); 33755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->startedQueries.clear(); 33765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->imageLayoutMap.clear(); 33775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->eventToStageMap.clear(); 33785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->drawData.clear(); 33795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->currentDrawData.buffers.clear(); 338058b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis pCB->vertex_buffer_used = false; 33815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->primaryCommandBuffer = VK_NULL_HANDLE; 3382bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis // Make sure any secondaryCommandBuffers are removed from globalInFlight 3383bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis for (auto secondary_cb : pCB->secondaryCommandBuffers) { 3384bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis dev_data->globalInFlightCmdBuffers.erase(secondary_cb); 3385bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis } 33865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->secondaryCommandBuffers.clear(); 33877a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis pCB->updateImages.clear(); 33887a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis pCB->updateBuffers.clear(); 3389400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis clear_cmd_buf_and_mem_references(dev_data, pCB); 3390b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine pCB->eventUpdates.clear(); 3391d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine pCB->queryUpdates.clear(); 339293c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski 3393bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis // Remove object bindings 3394bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis for (auto obj : pCB->object_bindings) { 3395bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis removeCommandBufferBinding(dev_data, &obj, pCB); 3396bf66bca5d96f2721897c5f3100da2df741da9addTobin Ehlis } 3397a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis pCB->object_bindings.clear(); 339893c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski // Remove this cmdBuffer's reference from each FrameBuffer's CB ref list 339993c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski for (auto framebuffer : pCB->framebuffers) { 34009a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto fb_state = GetFramebufferState(dev_data, framebuffer); 3401cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (fb_state) fb_state->cb_bindings.erase(pCB); 340293c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski } 340393c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski pCB->framebuffers.clear(); 34047003b38da5cc27a063af3c45080f3a35438283eeTobin Ehlis pCB->activeFramebuffer = VK_NULL_HANDLE; 34055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 34065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 34075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 34085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Set PSO-related status bits for CB, including dynamic state set via PSO 34094c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlisstatic void set_cb_pso_status(GLOBAL_CB_NODE *pCB, const PIPELINE_STATE *pPipe) { 34105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Account for any dynamic state not set via this PSO 3411ca546210846c65808717f8875deae39bd227c240Tobin Ehlis if (!pPipe->graphicsPipelineCI.pDynamicState || 3412cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski !pPipe->graphicsPipelineCI.pDynamicState->dynamicStateCount) { // All state is static 34134052946ae557337ff95f3725e879131b1c63f865Tobin Ehlis pCB->status |= CBSTATUS_ALL_STATE_SET; 34145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 34155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // First consider all state on 34165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Then unset any state that's noted as dynamic in PSO 34175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Finally OR that into CB statemask 34184052946ae557337ff95f3725e879131b1c63f865Tobin Ehlis CBStatusFlags psoDynStateMask = CBSTATUS_ALL_STATE_SET; 3419ca546210846c65808717f8875deae39bd227c240Tobin Ehlis for (uint32_t i = 0; i < pPipe->graphicsPipelineCI.pDynamicState->dynamicStateCount; i++) { 3420ca546210846c65808717f8875deae39bd227c240Tobin Ehlis switch (pPipe->graphicsPipelineCI.pDynamicState->pDynamicStates[i]) { 3421cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DYNAMIC_STATE_LINE_WIDTH: 3422cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski psoDynStateMask &= ~CBSTATUS_LINE_WIDTH_SET; 3423cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3424cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DYNAMIC_STATE_DEPTH_BIAS: 3425cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski psoDynStateMask &= ~CBSTATUS_DEPTH_BIAS_SET; 3426cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3427cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DYNAMIC_STATE_BLEND_CONSTANTS: 3428cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski psoDynStateMask &= ~CBSTATUS_BLEND_CONSTANTS_SET; 3429cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3430cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DYNAMIC_STATE_DEPTH_BOUNDS: 3431cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski psoDynStateMask &= ~CBSTATUS_DEPTH_BOUNDS_SET; 3432cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3433cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK: 3434cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski psoDynStateMask &= ~CBSTATUS_STENCIL_READ_MASK_SET; 3435cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3436cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DYNAMIC_STATE_STENCIL_WRITE_MASK: 3437cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski psoDynStateMask &= ~CBSTATUS_STENCIL_WRITE_MASK_SET; 3438cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3439cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case VK_DYNAMIC_STATE_STENCIL_REFERENCE: 3440cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski psoDynStateMask &= ~CBSTATUS_STENCIL_REFERENCE_SET; 3441cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 3442cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 3443cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // TODO : Flag error here 3444cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 34455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 34465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 34475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->status |= psoDynStateMask; 34485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 34495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 34505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3451623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski// Flags validation error if the associated call is made inside a render pass. The apiName routine should ONLY be called outside a 3452623784ad78c8b77a78c4db613db974c12e5f5a43Mark Lobodzinski// render pass. 345351ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisbool insideRenderPass(const layer_data *dev_data, GLOBAL_CB_NODE *pCB, const char *apiName, UNIQUE_VALIDATION_ERROR_CODE msgCode) { 3454e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool inside = false; 34555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB->activeRenderPass) { 345651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis inside = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 3457ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen (uint64_t)pCB->commandBuffer, __LINE__, msgCode, "DS", 3458ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen "%s: It is invalid to issue this call inside an active render pass (0x%" PRIxLEAST64 "). %s", apiName, 3459ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen (uint64_t)pCB->activeRenderPass->renderPass, validation_error_map[msgCode]); 34605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 34615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return inside; 34625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 34635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 34645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Flags validation error if the associated call is made outside a render pass. The apiName 34655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// routine should ONLY be called inside a render pass. 346651ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisbool outsideRenderPass(const layer_data *dev_data, GLOBAL_CB_NODE *pCB, const char *apiName, UNIQUE_VALIDATION_ERROR_CODE msgCode) { 3467e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool outside = false; 34685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (((pCB->createInfo.level == VK_COMMAND_BUFFER_LEVEL_PRIMARY) && (!pCB->activeRenderPass)) || 34695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis ((pCB->createInfo.level == VK_COMMAND_BUFFER_LEVEL_SECONDARY) && (!pCB->activeRenderPass) && 34705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis !(pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT))) { 347151ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis outside = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 3472ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen (uint64_t)pCB->commandBuffer, __LINE__, msgCode, "DS", 3473ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen "%s: This call must be issued inside an active render pass. %s", apiName, validation_error_map[msgCode]); 34745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 34755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return outside; 34765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 34775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3478f0f7d8aa2286bd7516d9fb5c2e58890505e3e5d4Chris Forbesstatic void init_core_validation(instance_layer_data *instance_data, const VkAllocationCallbacks *pAllocator) { 3479b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis layer_debug_actions(instance_data->report_data, instance_data->logging_callback, pAllocator, "lunarg_core_validation"); 34805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 34815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3482747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbesstatic void checkInstanceRegisterExtensions(const VkInstanceCreateInfo *pCreateInfo, instance_layer_data *instance_data) { 3483747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) { 3484747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SURFACE_EXTENSION_NAME)) 3485747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->surfaceExtensionEnabled = true; 3486747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_DISPLAY_EXTENSION_NAME)) 3487747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->displayExtensionEnabled = true; 3488747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_ANDROID_KHR 3489747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_ANDROID_SURFACE_EXTENSION_NAME)) 3490747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->androidSurfaceExtensionEnabled = true; 3491747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif 3492747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_MIR_KHR 3493747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_MIR_SURFACE_EXTENSION_NAME)) 3494747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->mirSurfaceExtensionEnabled = true; 3495747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif 3496747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_WAYLAND_KHR 3497747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME)) 3498747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->waylandSurfaceExtensionEnabled = true; 3499747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif 3500747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_WIN32_KHR 3501747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_WIN32_SURFACE_EXTENSION_NAME)) 3502747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->win32SurfaceExtensionEnabled = true; 3503747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif 3504747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_XCB_KHR 3505747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_XCB_SURFACE_EXTENSION_NAME)) 3506747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->xcbSurfaceExtensionEnabled = true; 3507747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif 3508747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_XLIB_KHR 3509747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_XLIB_SURFACE_EXTENSION_NAME)) 3510747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->xlibSurfaceExtensionEnabled = true; 3511747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#endif 3512747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes } 3513747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 3514747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 35157a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis// For the given ValidationCheck enum, set all relevant instance disabled flags to true 35167a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlisvoid SetDisabledFlags(instance_layer_data *instance_data, VkValidationFlagsEXT *val_flags_struct) { 35177a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis for (uint32_t i = 0; i < val_flags_struct->disabledValidationCheckCount; ++i) { 35187a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis switch (val_flags_struct->pDisabledValidationChecks[i]) { 35197a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis case VK_VALIDATION_CHECK_ALL_EXT: 35207a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis // Set all disabled flags to true 35217a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis instance_data->disabled.SetAll(true); 35227a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis break; 35237a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis default: 35247a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis break; 35257a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis } 35267a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis } 35277a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis} 35287a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis 3529bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, 3530bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkInstance *pInstance) { 35315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO); 35325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 35335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(chain_info->u.pLayerInfo); 35345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr; 35355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance"); 3536cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (fpCreateInstance == NULL) return VK_ERROR_INITIALIZATION_FAILED; 35375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 35385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Advance the link info for the next element on the chain 35395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext; 35405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 35415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance); 3542cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (result != VK_SUCCESS) return result; 35435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 354456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(*pInstance), instance_layer_data_map); 354556a5ba3e60a723781945959ffc10e2e215350de5Chia-I Wu instance_data->instance = *pInstance; 35469172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes layer_init_instance_dispatch_table(*pInstance, &instance_data->dispatch_table, fpGetInstanceProcAddr); 35479172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes instance_data->report_data = debug_report_create_instance( 35489172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes &instance_data->dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount, pCreateInfo->ppEnabledExtensionNames); 3549747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes checkInstanceRegisterExtensions(pCreateInfo, instance_data); 3550b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis init_core_validation(instance_data, pAllocator); 3551825ac70f99460ccb9494d34f93d8ee7ec303e5deMark Lobodzinski 35525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis ValidateLayerOrdering(*pCreateInfo); 35537a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis // Parse any pNext chains 35547a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis if (pCreateInfo->pNext) { 35557a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis GENERIC_HEADER *struct_header = (GENERIC_HEADER *)pCreateInfo->pNext; 35567a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis while (struct_header) { 35577a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis // Check for VkValidationFlagsExt 35587a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis if (VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT == struct_header->sType) { 35597a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis SetDisabledFlags(instance_data, (VkValidationFlagsEXT *)struct_header); 35607a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis } 35617a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis struct_header = (GENERIC_HEADER *)struct_header->pNext; 35627a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis } 35637a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis } 35645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 35655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 35665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 35675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 356825002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// Hook DestroyInstance to remove tableInstanceMap entry 356989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) { 35705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODOSC : Shouldn't need any customization here 35715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dispatch_key key = get_dispatch_key(instance); 35725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TBD: Need any locking this early, in case this function is called at the 35735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // same time by more than one thread? 357456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(key, instance_layer_data_map); 35759172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes instance_data->dispatch_table.DestroyInstance(instance, pAllocator); 35765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3577b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 35785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Clean up logging callback, if any 35799172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes while (instance_data->logging_callback.size() > 0) { 35809172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes VkDebugReportCallbackEXT callback = instance_data->logging_callback.back(); 35819172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes layer_destroy_msg_callback(instance_data->report_data, callback, pAllocator); 35829172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes instance_data->logging_callback.pop_back(); 35835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 35845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 35859172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes layer_debug_report_destroy_instance(instance_data->report_data); 35865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis layer_data_map.erase(key); 35875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 35885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 358915ff171550065db9f978e9d0d639629beae3038fChris Forbesstatic void checkDeviceRegisterExtensions(const VkDeviceCreateInfo *pCreateInfo, devExts *exts) { 359015ff171550065db9f978e9d0d639629beae3038fChris Forbes 359115ff171550065db9f978e9d0d639629beae3038fChris Forbes static const std::pair<char const *, bool devExts::*> known_extensions[] { 3592599899dabe438a8ea144c0add628d3f5afe54dd0Chris Forbes {VK_KHR_SWAPCHAIN_EXTENSION_NAME, &devExts::khr_swapchain_enabled}, 3593599899dabe438a8ea144c0add628d3f5afe54dd0Chris Forbes {VK_KHR_DISPLAY_SWAPCHAIN_EXTENSION_NAME, &devExts::khr_display_swapchain_enabled}, 359415ff171550065db9f978e9d0d639629beae3038fChris Forbes {VK_NV_GLSL_SHADER_EXTENSION_NAME, &devExts::nv_glsl_shader_enabled}, 359515ff171550065db9f978e9d0d639629beae3038fChris Forbes {VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME, &devExts::khr_descriptor_update_template_enabled}, 359615ff171550065db9f978e9d0d639629beae3038fChris Forbes {VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME, &devExts::khr_shader_draw_parameters_enabled}, 359715ff171550065db9f978e9d0d639629beae3038fChris Forbes {VK_KHR_MAINTENANCE1_EXTENSION_NAME, &devExts::khr_maintenance1_enabled}, 359815ff171550065db9f978e9d0d639629beae3038fChris Forbes {VK_NV_GEOMETRY_SHADER_PASSTHROUGH_EXTENSION_NAME, &devExts::nv_geometry_shader_passthrough_enabled}, 359915ff171550065db9f978e9d0d639629beae3038fChris Forbes {VK_NV_SAMPLE_MASK_OVERRIDE_COVERAGE_EXTENSION_NAME, &devExts::nv_sample_mask_override_coverage_enabled}, 360015ff171550065db9f978e9d0d639629beae3038fChris Forbes {VK_NV_VIEWPORT_ARRAY2_EXTENSION_NAME, &devExts::nv_viewport_array2_enabled}, 360115ff171550065db9f978e9d0d639629beae3038fChris Forbes {VK_EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME, &devExts::khr_subgroup_ballot_enabled}, 360215ff171550065db9f978e9d0d639629beae3038fChris Forbes {VK_EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME, &devExts::khr_subgroup_vote_enabled}, 360315ff171550065db9f978e9d0d639629beae3038fChris Forbes }; 36045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 36053f253ab4d7ecd9a232fd7ead50fe5d44ddd1cd58Chris Forbes for (auto ext : known_extensions) { 36063f253ab4d7ecd9a232fd7ead50fe5d44ddd1cd58Chris Forbes exts->*(ext.second) = false; 36073f253ab4d7ecd9a232fd7ead50fe5d44ddd1cd58Chris Forbes } 36083f253ab4d7ecd9a232fd7ead50fe5d44ddd1cd58Chris Forbes 360915ff171550065db9f978e9d0d639629beae3038fChris Forbes for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) { 361015ff171550065db9f978e9d0d639629beae3038fChris Forbes for (auto ext : known_extensions) { 361115ff171550065db9f978e9d0d639629beae3038fChris Forbes if (!strcmp(ext.first, pCreateInfo->ppEnabledExtensionNames[i])) { 361215ff171550065db9f978e9d0d639629beae3038fChris Forbes exts->*(ext.second) = true; 361315ff171550065db9f978e9d0d639629beae3038fChris Forbes break; 361415ff171550065db9f978e9d0d639629beae3038fChris Forbes } 3615ae17c7b673b9763c8e74bb70ed9e53b00aca8081Mark Lobodzinski } 36165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 36175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 36185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3619838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski// Verify that queue family has been properly requested 3620ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblenstatic bool ValidateRequestedQueueFamilyProperties(instance_layer_data *instance_data, VkPhysicalDevice gpu, 3621ff97d1b78192ab7853965cd7a0462273c4813333Mike Weiblen const VkDeviceCreateInfo *create_info) { 36223251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 36239a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto physical_device_state = GetPhysicalDeviceState(instance_data, gpu); 3624838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski // First check is app has actually requested queueFamilyProperties 36254b293996aa6a9bd92ef1f0175eca4b0e8a9fd9fcChris Forbes if (!physical_device_state) { 36263251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 36273251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski 0, __LINE__, DEVLIMITS_MUST_QUERY_COUNT, "DL", 36283251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Invalid call to vkCreateDevice() w/o first calling vkEnumeratePhysicalDevices()."); 36294b293996aa6a9bd92ef1f0175eca4b0e8a9fd9fcChris Forbes } else if (QUERY_DETAILS != physical_device_state->vkGetPhysicalDeviceQueueFamilyPropertiesState) { 3630838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski // TODO: This is not called out as an invalid use in the spec so make more informative recommendation. 36313251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, 36323251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_INVALID_QUEUE_CREATE_REQUEST, "DL", 36333251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Call to vkCreateDevice() w/o first calling vkGetPhysicalDeviceQueueFamilyProperties()."); 3634838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski } else { 3635838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski // Check that the requested queue properties are valid 3636838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski for (uint32_t i = 0; i < create_info->queueCreateInfoCount; i++) { 3637838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski uint32_t requestedIndex = create_info->pQueueCreateInfos[i].queueFamilyIndex; 36387d8b6ab1b68c397da50bad43deb1fba389ebace7Chris Forbes if (requestedIndex >= physical_device_state->queue_family_properties.size()) { 36393251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg( 36404b293996aa6a9bd92ef1f0175eca4b0e8a9fd9fcChris Forbes instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, 3641838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski __LINE__, DEVLIMITS_INVALID_QUEUE_CREATE_REQUEST, "DL", 3642838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski "Invalid queue create request in vkCreateDevice(). Invalid queueFamilyIndex %u requested.", requestedIndex); 3643838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski } else if (create_info->pQueueCreateInfos[i].queueCount > 36447d8b6ab1b68c397da50bad43deb1fba389ebace7Chris Forbes physical_device_state->queue_family_properties[requestedIndex].queueCount) { 36453251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 36463251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, 36473251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski DEVLIMITS_INVALID_QUEUE_CREATE_REQUEST, "DL", 36483251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Invalid queue create request in vkCreateDevice(). QueueFamilyIndex %u only has %u queues, but " 36493251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "requested queueCount is %u.", 36503251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski requestedIndex, physical_device_state->queue_family_properties[requestedIndex].queueCount, 36513251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski create_info->pQueueCreateInfos[i].queueCount); 3652838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski } 3653838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski } 3654838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski } 36553251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 3656838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski} 3657838e3917bc1a0479174dd753b5c28b8b2cf1954dMark Lobodzinski 3658f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski// Verify that features have been queried and that they are available 3659bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic bool ValidateRequestedFeatures(instance_layer_data *dev_data, VkPhysicalDevice phys, 3660bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkPhysicalDeviceFeatures *requested_features) { 36613251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 3662f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski 36639a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto phys_device_state = GetPhysicalDeviceState(dev_data, phys); 36643bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes const VkBool32 *actual = reinterpret_cast<VkBool32 *>(&phys_device_state->features); 3665825ac70f99460ccb9494d34f93d8ee7ec303e5deMark Lobodzinski const VkBool32 *requested = reinterpret_cast<const VkBool32 *>(requested_features); 3666f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski // TODO : This is a nice, compact way to loop through struct, but a bad way to report issues 3667f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski // Need to provide the struct member name with the issue. To do that seems like we'll 3668f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski // have to loop through each struct member which should be done w/ codegen to keep in synch. 3669f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski uint32_t errors = 0; 3670f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski uint32_t total_bools = sizeof(VkPhysicalDeviceFeatures) / sizeof(VkBool32); 3671f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski for (uint32_t i = 0; i < total_bools; i++) { 3672f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski if (requested[i] > actual[i]) { 3673f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski // TODO: Add index to struct member name helper to be able to include a feature name 36743251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 36753251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski 0, __LINE__, DEVLIMITS_INVALID_FEATURE_REQUESTED, "DL", 36763251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "While calling vkCreateDevice(), requesting feature #%u in VkPhysicalDeviceFeatures struct, " 36773251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "which is not available on this device.", 36783251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski i); 3679f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski errors++; 3680f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski } 3681f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski } 36823bb2c67470811e4eaf908b3eade82f73aa3f87bcChris Forbes if (errors && (UNCALLED == phys_device_state->vkGetPhysicalDeviceFeaturesState)) { 3683f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski // If user didn't request features, notify them that they should 3684f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski // TODO: Verify this against the spec. I believe this is an invalid use of the API and should return an error 36853251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, 36863251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski __LINE__, DEVLIMITS_INVALID_FEATURE_REQUESTED, "DL", 36873251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "You requested features that are unavailable on this device. You should first query feature " 36883251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "availability by calling vkGetPhysicalDeviceFeatures()."); 3689f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski } 36903251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 3691f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski} 3692f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski 369389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo, 369489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) { 369556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(gpu), instance_layer_data_map); 36963251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 3697f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski 3698f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski // Check that any requested features are available 3699f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski if (pCreateInfo->pEnabledFeatures) { 37003251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateRequestedFeatures(instance_data, gpu, pCreateInfo->pEnabledFeatures); 3701f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski } 37023251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateRequestedQueueFamilyProperties(instance_data, gpu, pCreateInfo); 3703f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski 37043251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (skip) { 37051d659b4113b77a95325df10d602a03f1e7abf8b7Mark Mueller return VK_ERROR_VALIDATION_FAILED_EXT; 37061d659b4113b77a95325df10d602a03f1e7abf8b7Mark Mueller } 37071d659b4113b77a95325df10d602a03f1e7abf8b7Mark Mueller 37085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO); 37095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 37105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis assert(chain_info->u.pLayerInfo); 37115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr; 37125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr; 371356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(instance_data->instance, "vkCreateDevice"); 37145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (fpCreateDevice == NULL) { 37155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return VK_ERROR_INITIALIZATION_FAILED; 37165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 37175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 37185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Advance the link info for the next element on the chain 37195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext; 37205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 37215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice); 37225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (result != VK_SUCCESS) { 37235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 37245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 37255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3726b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 372756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *device_data = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map); 37285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 372956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis device_data->instance_data = instance_data; 37305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Setup device dispatch table 373156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_init_device_dispatch_table(*pDevice, &device_data->dispatch_table, fpGetDeviceProcAddr); 373256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis device_data->device = *pDevice; 3733ec85232c4d8d9ddf7d2ae57cb8203c5ab52c1106Mark Lobodzinski // Save PhysicalDevice handle 373456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis device_data->physical_device = gpu; 37355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 373656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis device_data->report_data = layer_debug_report_create_device(instance_data->report_data, *pDevice); 373715ff171550065db9f978e9d0d639629beae3038fChris Forbes checkDeviceRegisterExtensions(pCreateInfo, &device_data->device_extensions); 37385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Get physical device limits for this device 373956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_data->dispatch_table.GetPhysicalDeviceProperties(gpu, &(device_data->phys_dev_properties.properties)); 37405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t count; 374156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_data->dispatch_table.GetPhysicalDeviceQueueFamilyProperties(gpu, &count, nullptr); 374256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis device_data->phys_dev_properties.queue_family_properties.resize(count); 374356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_data->dispatch_table.GetPhysicalDeviceQueueFamilyProperties( 374456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis gpu, &count, &device_data->phys_dev_properties.queue_family_properties[0]); 37455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODO: device limits should make sure these are compatible 37465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCreateInfo->pEnabledFeatures) { 374756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis device_data->enabled_features = *pCreateInfo->pEnabledFeatures; 37485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 374956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis memset(&device_data->enabled_features, 0, sizeof(VkPhysicalDeviceFeatures)); 37505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 3751e47dbc3f3340fa177d877a67b2adb76a570027e5Mark Lobodzinski // Store physical device properties and physical device mem limits into device layer_data structs 375256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_data->dispatch_table.GetPhysicalDeviceMemoryProperties(gpu, &device_data->phys_dev_mem_props); 375356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_data->dispatch_table.GetPhysicalDeviceProperties(gpu, &device_data->phys_dev_props); 3754b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 37555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 37565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis ValidateLayerOrdering(*pCreateInfo); 37575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 37585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 37595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 37605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 37615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// prototype 376289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) { 37635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODOSC : Shouldn't need any customization here 37643ec39aeb6d6f08fb1ee45f64f72543a710754c62Tobin Ehlis bool skip = false; 37655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dispatch_key key = get_dispatch_key(device); 376656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(key, layer_data_map); 37675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Free all the memory 3768b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 37695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis deletePipelines(dev_data); 3770fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes dev_data->renderPassMap.clear(); 37719b36ac77fbf55bd7ffdeb9020f2277fff3a5a807Chris Forbes for (auto ii = dev_data->commandBufferMap.begin(); ii != dev_data->commandBufferMap.end(); ++ii) { 37729b36ac77fbf55bd7ffdeb9020f2277fff3a5a807Chris Forbes delete (*ii).second; 37739b36ac77fbf55bd7ffdeb9020f2277fff3a5a807Chris Forbes } 37749b36ac77fbf55bd7ffdeb9020f2277fff3a5a807Chris Forbes dev_data->commandBufferMap.clear(); 3775f13bee0887f3c3d1d597c82869864be3be836737Tobin Ehlis // This will also delete all sets in the pool & remove them from setMap 37765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis deletePools(dev_data); 3777f13bee0887f3c3d1d597c82869864be3be836737Tobin Ehlis // All sets should be removed 3778f13bee0887f3c3d1d597c82869864be3be836737Tobin Ehlis assert(dev_data->setMap.empty()); 3779a1e5173c89eb7f03e0434ad45ccd1471e722fa71Tobin Ehlis for (auto del_layout : dev_data->descriptorSetLayoutMap) { 3780a1e5173c89eb7f03e0434ad45ccd1471e722fa71Tobin Ehlis delete del_layout.second; 3781a1e5173c89eb7f03e0434ad45ccd1471e722fa71Tobin Ehlis } 3782fce842878e9ddcc7f37e1c457a4b018d52358087Tobin Ehlis dev_data->descriptorSetLayoutMap.clear(); 37835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->imageViewMap.clear(); 37845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->imageMap.clear(); 37855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->imageSubresourceMap.clear(); 37865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->imageLayoutMap.clear(); 37875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->bufferViewMap.clear(); 37885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->bufferMap.clear(); 37891344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis // Queues persist until device is destroyed 37901344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis dev_data->queueMap.clear(); 37915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Report any memory leaks 37925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis layer_debug_report_destroy_device(device); 3793b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 37945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 37955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#if DISPATCH_MAP_DEBUG 3796414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller fprintf(stderr, "Device: 0x%p, key: 0x%p\n", device, key); 37975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis#endif 37983ec39aeb6d6f08fb1ee45f64f72543a710754c62Tobin Ehlis if (!skip) { 37994a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyDevice(device, pAllocator); 38003ec39aeb6d6f08fb1ee45f64f72543a710754c62Tobin Ehlis layer_data_map.erase(key); 38015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 38025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 38035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 38045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}}; 38055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3806208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis// For given stage mask, if Geometry shader stage is on w/o GS being enabled, report geo_error_id 3807208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis// and if Tessellation Control or Evaluation shader stages are on w/o TS being enabled, report tess_error_id 3808208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlisstatic bool ValidateStageMaskGsTsEnables(layer_data *dev_data, VkPipelineStageFlags stageMask, const char *caller, 3809208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis UNIQUE_VALIDATION_ERROR_CODE geo_error_id, UNIQUE_VALIDATION_ERROR_CODE tess_error_id) { 3810208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis bool skip = false; 3811208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis if (!dev_data->enabled_features.geometryShader && (stageMask & VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT)) { 3812208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 3813cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski geo_error_id, "DL", 3814cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s call includes a stageMask with VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT bit set when " 3815cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "device does not have geometryShader feature enabled. %s", 3816208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis caller, validation_error_map[geo_error_id]); 3817208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis } 3818208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis if (!dev_data->enabled_features.tessellationShader && 3819208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis (stageMask & (VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT | VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT))) { 3820208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 3821cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski tess_error_id, "DL", 3822cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s call includes a stageMask with VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT " 3823cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "and/or VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT bit(s) set when device " 3824cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "does not have tessellationShader feature enabled. %s", 3825208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis caller, validation_error_map[tess_error_id]); 3826208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis } 3827208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis return skip; 3828208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis} 3829208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis 3830ad97d033b614e6265aaa8c8f0d21a044982d4de7Jeremy Hayes// Loop through bound objects and increment their in_use counts. 3831ad97d033b614e6265aaa8c8f0d21a044982d4de7Jeremy Hayesstatic void IncrementBoundObjects(layer_data *dev_data, GLOBAL_CB_NODE const *cb_node) { 3832a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis for (auto obj : cb_node->object_bindings) { 3833a317e7593a0fe227635fc8241908471acb36c952Chris Forbes auto base_obj = GetStateStructPtrFromObject(dev_data, obj); 3834ad97d033b614e6265aaa8c8f0d21a044982d4de7Jeremy Hayes if (base_obj) { 383551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour base_obj->in_use.fetch_add(1); 3836162dac96d3883e8fffaa1f988043f62c06662d2eTobin Ehlis } 3837a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis } 3838a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis} 38395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// Track which resources are in-flight by atomically incrementing their "in_use" count 384051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourstatic void incrementResources(layer_data *dev_data, GLOBAL_CB_NODE *cb_node) { 384151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour cb_node->submitCount++; 38429a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis cb_node->in_use.fetch_add(1); 38439a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis dev_data->globalInFlightCmdBuffers.insert(cb_node->commandBuffer); 3844a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes 3845a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis // First Increment for all "generic" objects bound to cmd buffer, followed by special-case objects below 3846ad97d033b614e6265aaa8c8f0d21a044982d4de7Jeremy Hayes IncrementBoundObjects(dev_data, cb_node); 3847a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis // TODO : We should be able to remove the NULL look-up checks from the code below as long as 3848a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis // all the corresponding cases are verified to cause CB_INVALID state and the CB_INVALID state 3849a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis // should then be flagged prior to calling this function 38509a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis for (auto drawDataElement : cb_node->drawData) { 38515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto buffer : drawDataElement.buffers) { 38529a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto buffer_state = GetBufferState(dev_data, buffer); 385351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (buffer_state) { 38545cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis buffer_state->in_use.fetch_add(1); 38555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 38565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 38575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 38589a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis for (auto event : cb_node->writeEventsBeforeWait) { 38599a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto event_state = GetEventNode(dev_data, event); 3860cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (event_state) event_state->write_in_use++; 3861c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine } 38625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 38635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 3864b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis// Note: This function assumes that the global lock is held by the calling thread. 3865b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis// For the given queue, verify the queue state up to the given seq number. 3866b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis// Currently the only check is to make sure that if there are events to be waited on prior to 3867b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis// a QueryReset, make sure that all such events have been signalled. 3868d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbesstatic bool VerifyQueueStateToSeq(layer_data *dev_data, QUEUE_STATE *initial_queue, uint64_t initial_seq) { 3869b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis bool skip = false; 3870d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes 3871d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes // sequence number we want to validate up to, per queue 3872d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes std::unordered_map<QUEUE_STATE *, uint64_t> target_seqs { { initial_queue, initial_seq } }; 3873d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes // sequence number we've completed validation for, per queue 3874d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes std::unordered_map<QUEUE_STATE *, uint64_t> done_seqs; 3875d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes std::vector<QUEUE_STATE *> worklist { initial_queue }; 3876d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes 3877d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes while (worklist.size()) { 3878d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes auto queue = worklist.back(); 3879d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes worklist.pop_back(); 3880d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes 3881d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes auto target_seq = target_seqs[queue]; 3882d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes auto seq = std::max(done_seqs[queue], queue->seq); 3883d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes auto sub_it = queue->submissions.begin() + int(seq - queue->seq); // seq >= queue->seq 3884d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes 3885d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes for (; seq < target_seq; ++sub_it, ++seq) { 3886d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes for (auto &wait : sub_it->waitSemaphores) { 3887d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes auto other_queue = GetQueueState(dev_data, wait.queue); 3888d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes 3889d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes if (other_queue == queue) 3890d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes continue; // semaphores /always/ point backwards, so no point here. 3891d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes 3892d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes auto other_target_seq = std::max(target_seqs[other_queue], wait.seq); 3893d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes auto other_done_seq = std::max(done_seqs[other_queue], other_queue->seq); 3894d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes 3895d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes // if this wait is for another queue, and covers new sequence 3896d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes // numbers beyond what we've already validated, mark the new 3897d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes // target seq and (possibly-re)add the queue to the worklist. 3898d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes if (other_done_seq < other_target_seq) { 3899d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes target_seqs[other_queue] = other_target_seq; 3900d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes worklist.push_back(other_queue); 3901d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes } 3902d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes } 3903d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes 3904d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes for (auto cb : sub_it->cbs) { 3905d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes auto cb_node = GetCBNode(dev_data, cb); 3906d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes if (cb_node) { 3907d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes for (auto queryEventsPair : cb_node->waitedEventsBeforeQueryReset) { 3908d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes for (auto event : queryEventsPair.second) { 3909d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes if (dev_data->eventMap[event].needsSignaled) { 3910d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 3911d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, 0, DRAWSTATE_INVALID_QUERY, "DS", 3912d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes "Cannot get query results on queryPool 0x%" PRIx64 3913d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes " with index %d which was guarded by unsignaled event 0x%" PRIx64 ".", 3914d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes (uint64_t)(queryEventsPair.first.pool), queryEventsPair.first.index, (uint64_t)(event)); 3915d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes } 3916b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis } 3917b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis } 3918b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine } 3919b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine } 3920b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine } 3921d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes 3922d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes // finally mark the point we've now validated this queue to. 3923d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes done_seqs[queue] = seq; 392492b1701c552e96e96fdbbb77e4b106a9526f3b8cTobin Ehlis } 3925d9944715fa5a4a750a26680f08e5defe85aa7a66Chris Forbes 3926b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis return skip; 3927b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis} 3928b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis 3929b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis// When the given fence is retired, verify outstanding queue operations through the point of the fence 3930b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlisstatic bool VerifyQueueStateToFence(layer_data *dev_data, VkFence fence) { 39319a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto fence_state = GetFenceNode(dev_data, fence); 3932b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis if (VK_NULL_HANDLE != fence_state->signaler.first) { 39339a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis return VerifyQueueStateToSeq(dev_data, GetQueueState(dev_data, fence_state->signaler.first), fence_state->signaler.second); 3934b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis } 3935b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis return false; 3936b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine} 39377d33205c3aa4aba751a2c07f956634aac616f916Chris Forbes 39387d33205c3aa4aba751a2c07f956634aac616f916Chris Forbes// TODO: nuke this completely. 3939b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine// Decrement cmd_buffer in_use and if it goes to 0 remove cmd_buffer from globalInFlightCmdBuffers 3940b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentinestatic inline void removeInFlightCmdBuffer(layer_data *dev_data, VkCommandBuffer cmd_buffer) { 3941b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine // Pull it off of global list initially, but if we find it in any other queue list, add it back in 39429a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, cmd_buffer); 3943b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine pCB->in_use.fetch_sub(1); 3944b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine if (!pCB->in_use.load()) { 3945b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine dev_data->globalInFlightCmdBuffers.erase(cmd_buffer); 3946b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine } 3947b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine} 3948b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine 3949a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis// Decrement in-use count for objects bound to command buffer 39502f8cbf3b166e175174877a59929902e005953d6dTobin Ehlisstatic void DecrementBoundResources(layer_data *dev_data, GLOBAL_CB_NODE const *cb_node) { 395100e8ce2e6c1c191758f7b7c15eeaf350e5b4a3b6Tobin Ehlis BASE_NODE *base_obj = nullptr; 3952a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis for (auto obj : cb_node->object_bindings) { 39537e5c0c26004626cf6826dfe2779a738a1f9f1fffTobin Ehlis base_obj = GetStateStructPtrFromObject(dev_data, obj); 395400e8ce2e6c1c191758f7b7c15eeaf350e5b4a3b6Tobin Ehlis if (base_obj) { 395500e8ce2e6c1c191758f7b7c15eeaf350e5b4a3b6Tobin Ehlis base_obj->in_use.fetch_sub(1); 395600e8ce2e6c1c191758f7b7c15eeaf350e5b4a3b6Tobin Ehlis } 3957a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis } 3958a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis} 3959da8f07baf262972eb3e719fa07b073c180dff157Chris Forbes 396036c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlisstatic void RetireWorkOnQueue(layer_data *dev_data, QUEUE_STATE *pQueue, uint64_t seq) { 39619867daedbf52debc77d6568162ee21e071699b80Chris Forbes std::unordered_map<VkQueue, uint64_t> otherQueueSeqs; 39629867daedbf52debc77d6568162ee21e071699b80Chris Forbes 39639867daedbf52debc77d6568162ee21e071699b80Chris Forbes // Roll this queue forward, one submission at a time. 39649867daedbf52debc77d6568162ee21e071699b80Chris Forbes while (pQueue->seq < seq) { 3965bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto &submission = pQueue->submissions.front(); 39669867daedbf52debc77d6568162ee21e071699b80Chris Forbes 3967bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski for (auto &wait : submission.waitSemaphores) { 39689a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pSemaphore = GetSemaphoreNode(dev_data, wait.semaphore); 3969c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski if (pSemaphore) { 3970c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski pSemaphore->in_use.fetch_sub(1); 3971c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski } 3972bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto &lastSeq = otherQueueSeqs[wait.queue]; 39739867daedbf52debc77d6568162ee21e071699b80Chris Forbes lastSeq = std::max(lastSeq, wait.seq); 3974da8f07baf262972eb3e719fa07b073c180dff157Chris Forbes } 3975cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes 3976bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski for (auto &semaphore : submission.signalSemaphores) { 39779a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pSemaphore = GetSemaphoreNode(dev_data, semaphore); 3978c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski if (pSemaphore) { 3979c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski pSemaphore->in_use.fetch_sub(1); 3980c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski } 39819867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 3982cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes 39839867daedbf52debc77d6568162ee21e071699b80Chris Forbes for (auto cb : submission.cbs) { 39849a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, cb); 3985c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski if (!cb_node) { 3986c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski continue; 3987c91c376e7f18eba22f2996e514eb4714417fb343Mark Lobodzinski } 3988a45bdcb94b2fbda36bc191e12cc20218f62fb0e0Tobin Ehlis // First perform decrement on general case bound objects 39899a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis DecrementBoundResources(dev_data, cb_node); 39909a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis for (auto drawDataElement : cb_node->drawData) { 39919867daedbf52debc77d6568162ee21e071699b80Chris Forbes for (auto buffer : drawDataElement.buffers) { 39929a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto buffer_state = GetBufferState(dev_data, buffer); 39935cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis if (buffer_state) { 39945cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis buffer_state->in_use.fetch_sub(1); 39959867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 39969867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 3997da8f07baf262972eb3e719fa07b073c180dff157Chris Forbes } 39989a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis for (auto event : cb_node->writeEventsBeforeWait) { 39999867daedbf52debc77d6568162ee21e071699b80Chris Forbes auto eventNode = dev_data->eventMap.find(event); 40009867daedbf52debc77d6568162ee21e071699b80Chris Forbes if (eventNode != dev_data->eventMap.end()) { 40019867daedbf52debc77d6568162ee21e071699b80Chris Forbes eventNode->second.write_in_use--; 40029867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 40039867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 40049a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis for (auto queryStatePair : cb_node->queryToStateMap) { 40059867daedbf52debc77d6568162ee21e071699b80Chris Forbes dev_data->queryToStateMap[queryStatePair.first] = queryStatePair.second; 40069867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 40079a61300d900fe3e43e9a03c7fa6876934bc1264eTobin Ehlis for (auto eventStagePair : cb_node->eventToStageMap) { 40089867daedbf52debc77d6568162ee21e071699b80Chris Forbes dev_data->eventMap[eventStagePair.first].stageMask = eventStagePair.second; 4009da8f07baf262972eb3e719fa07b073c180dff157Chris Forbes } 40100a32ed7bdf03e7bda914e03c0bfa6ebf400cdf5bMichael Lentine 40119867daedbf52debc77d6568162ee21e071699b80Chris Forbes removeInFlightCmdBuffer(dev_data, cb); 40120a32ed7bdf03e7bda914e03c0bfa6ebf400cdf5bMichael Lentine } 40139867daedbf52debc77d6568162ee21e071699b80Chris Forbes 40149a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pFence = GetFenceNode(dev_data, submission.fence); 40159867daedbf52debc77d6568162ee21e071699b80Chris Forbes if (pFence) { 40169867daedbf52debc77d6568162ee21e071699b80Chris Forbes pFence->state = FENCE_RETIRED; 40170a32ed7bdf03e7bda914e03c0bfa6ebf400cdf5bMichael Lentine } 40189867daedbf52debc77d6568162ee21e071699b80Chris Forbes 40199867daedbf52debc77d6568162ee21e071699b80Chris Forbes pQueue->submissions.pop_front(); 40209867daedbf52debc77d6568162ee21e071699b80Chris Forbes pQueue->seq++; 4021b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine } 40229867daedbf52debc77d6568162ee21e071699b80Chris Forbes 40239867daedbf52debc77d6568162ee21e071699b80Chris Forbes // Roll other queues forward to the highest seq we saw a wait for 40249867daedbf52debc77d6568162ee21e071699b80Chris Forbes for (auto qs : otherQueueSeqs) { 40259a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis RetireWorkOnQueue(dev_data, GetQueueState(dev_data, qs.first), qs.second); 4026d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 40279867daedbf52debc77d6568162ee21e071699b80Chris Forbes} 4028651d92815dfff917308137bb67aacccc4f60df86Chris Forbes 4029651d92815dfff917308137bb67aacccc4f60df86Chris Forbes// Submit a fence to a queue, delimiting previous fences and previous untracked 4030651d92815dfff917308137bb67aacccc4f60df86Chris Forbes// work by it. 403136c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlisstatic void SubmitFence(QUEUE_STATE *pQueue, FENCE_NODE *pFence, uint64_t submitCount) { 4032cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes pFence->state = FENCE_INFLIGHT; 40339867daedbf52debc77d6568162ee21e071699b80Chris Forbes pFence->signaler.first = pQueue->queue; 40349867daedbf52debc77d6568162ee21e071699b80Chris Forbes pFence->signaler.second = pQueue->seq + pQueue->submissions.size() + submitCount; 4035b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine} 4036b3d308d63ba34f40839f009ac83b33962d7f26b2Michael Lentine 403751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourstatic bool validateCommandBufferSimultaneousUse(layer_data *dev_data, GLOBAL_CB_NODE *pCB, int current_submit_count) { 40383251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 403951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if ((dev_data->globalInFlightCmdBuffers.count(pCB->commandBuffer) || current_submit_count > 1) && 40405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis !(pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT)) { 40413251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, 40423251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski __LINE__, VALIDATION_ERROR_00133, "DS", 40433251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Command Buffer 0x%p is already in use and is not marked for simultaneous use. %s", pCB->commandBuffer, 40443251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski validation_error_map[VALIDATION_ERROR_00133]); 40455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 40463251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 40475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 40485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4049946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinskistatic bool validateCommandBufferState(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, const char *call_source, 4050440bdd357701497c3442e3515f12ac1cfffc180aTony Barbour int current_submit_count) { 4051c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis bool skip = false; 4052cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.command_buffer_state) return skip; 40530a59acde4b40fde3bbfea5811d2abf2c85ca62f4Tobin Ehlis // Validate ONE_TIME_SUBMIT_BIT CB is not being submitted more than once 4054946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if ((cb_state->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT) && 4055946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski (cb_state->submitCount + current_submit_count > 1)) { 4056c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, 4057c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis __LINE__, DRAWSTATE_COMMAND_BUFFER_SINGLE_SUBMIT_VIOLATION, "DS", 4058226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "Commandbuffer 0x%p was begun w/ VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT " 4059c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis "set, but has been submitted 0x%" PRIxLEAST64 " times.", 4060946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->commandBuffer, cb_state->submitCount + current_submit_count); 40610a59acde4b40fde3bbfea5811d2abf2c85ca62f4Tobin Ehlis } 40625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Validate that cmd buffers have been updated 4063946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (CB_RECORDED != cb_state->state) { 4064946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (CB_INVALID == cb_state->state) { 4065946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ReportInvalidCommandBuffer(dev_data, cb_state, call_source); 4066cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else { // Flag error for using CB w/o vkEndCommandBuffer() called 4067c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 4068946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski (uint64_t)(cb_state->commandBuffer), __LINE__, DRAWSTATE_NO_END_COMMAND_BUFFER, "DS", 4069946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "You must call vkEndCommandBuffer() on command buffer 0x%p before this call to %s!", 4070946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->commandBuffer, call_source); 40715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 40725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 4073c264142df95edb7eb96b5dc2d87562efce6ded43Tobin Ehlis return skip; 40745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 40755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 407651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourstatic bool validateResources(layer_data *dev_data, GLOBAL_CB_NODE *cb_node) { 40773251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 407851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 407951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour // TODO : We should be able to remove the NULL look-up checks from the code below as long as 408051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour // all the corresponding cases are verified to cause CB_INVALID state and the CB_INVALID state 408151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour // should then be flagged prior to calling this function 408251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour for (auto drawDataElement : cb_node->drawData) { 408351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour for (auto buffer : drawDataElement.buffers) { 408451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour auto buffer_state = GetBufferState(dev_data, buffer); 408551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (!buffer_state) { 40863251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, 40873251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski (uint64_t)(buffer), __LINE__, DRAWSTATE_INVALID_BUFFER, "DS", 40883251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Cannot submit cmd buffer using deleted buffer 0x%" PRIx64 ".", (uint64_t)(buffer)); 408951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 409051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 409151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 40923251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 409351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour} 409451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 4095f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski// Check that the queue family index of 'queue' matches one of the entries in pQueueFamilyIndices 4096f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinskibool ValidImageBufferQueue(layer_data *dev_data, GLOBAL_CB_NODE *cb_node, const VK_OBJECT *object, VkQueue queue, uint32_t count, 4097f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski const uint32_t *indices) { 4098f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski bool found = false; 4099f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski bool skip = false; 4100f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski auto queue_state = GetQueueState(dev_data, queue); 4101f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski if (queue_state) { 4102f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski for (uint32_t i = 0; i < count; i++) { 4103f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski if (indices[i] == queue_state->queueFamilyIndex) { 4104f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski found = true; 4105f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski break; 4106f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski } 4107f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski } 4108f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski 4109f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski if (!found) { 411002a510945ff39f3d9e486e456aca5bfa6ea0c43aMark Lobodzinski skip = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, get_debug_report_enum[object->type], 411102a510945ff39f3d9e486e456aca5bfa6ea0c43aMark Lobodzinski object->handle, __LINE__, DRAWSTATE_INVALID_QUEUE_FAMILY, "DS", 4112f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski "vkQueueSubmit: Command buffer 0x%" PRIxLEAST64 " contains %s 0x%" PRIxLEAST64 4113f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski " which was not created allowing concurrent access to this queue family %d.", 41147a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski reinterpret_cast<uint64_t>(cb_node->commandBuffer), object_string[object->type], object->handle, 4115f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski queue_state->queueFamilyIndex); 4116f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski } 4117f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski } 4118f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski return skip; 4119f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski} 4120f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski 41217bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski// Validate that queueFamilyIndices of primary command buffers match this queue 41227bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski// Secondary command buffers were previously validated in vkCmdExecuteCommands(). 41237bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinskistatic bool validateQueueFamilyIndices(layer_data *dev_data, GLOBAL_CB_NODE *pCB, VkQueue queue) { 41243251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 41259a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pPool = GetCommandPoolNode(dev_data, pCB->createInfo.commandPool); 41269a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto queue_state = GetQueueState(dev_data, queue); 41277bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski 4128f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski if (pPool && queue_state) { 4129f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski if (pPool->queueFamilyIndex != queue_state->queueFamilyIndex) { 41303251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 41313251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t>(pCB->commandBuffer), __LINE__, VALIDATION_ERROR_00139, "DS", 41323251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkQueueSubmit: Primary command buffer 0x%p created in queue family %d is being submitted on queue " 41333251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "0x%p from queue family %d. %s", 41343251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski pCB->commandBuffer, pPool->queueFamilyIndex, queue, queue_state->queueFamilyIndex, 41353251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski validation_error_map[VALIDATION_ERROR_00139]); 4136f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski } 4137f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski 4138f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski // Ensure that any bound images or buffers created with SHARING_MODE_CONCURRENT have access to the current queue family 4139f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski for (auto object : pCB->object_bindings) { 41407a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski if (object.type == kVulkanObjectTypeImage) { 4141f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski auto image_state = GetImageState(dev_data, reinterpret_cast<VkImage &>(object.handle)); 4142f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski if (image_state && image_state->createInfo.sharingMode == VK_SHARING_MODE_CONCURRENT) { 41433251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidImageBufferQueue(dev_data, pCB, &object, queue, image_state->createInfo.queueFamilyIndexCount, 41443251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski image_state->createInfo.pQueueFamilyIndices); 4145f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski } 41467a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski } else if (object.type == kVulkanObjectTypeBuffer) { 4147f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski auto buffer_state = GetBufferState(dev_data, reinterpret_cast<VkBuffer &>(object.handle)); 4148f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski if (buffer_state && buffer_state->createInfo.sharingMode == VK_SHARING_MODE_CONCURRENT) { 41493251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidImageBufferQueue(dev_data, pCB, &object, queue, buffer_state->createInfo.queueFamilyIndexCount, 41503251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski buffer_state->createInfo.pQueueFamilyIndices); 4151f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski } 4152f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski } 4153f26f0f4b1c6b014d9abc2414a9ed255ecade9f04Mark Lobodzinski } 41547bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski } 41557bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski 41563251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 41577bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski} 41587bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski 415951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourstatic bool validatePrimaryCommandBufferState(layer_data *dev_data, GLOBAL_CB_NODE *pCB, int current_submit_count) { 41605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Track in-use for resources off of primary and any secondary CBs 41613251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 4162a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes 4163a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes // If USAGE_SIMULTANEOUS_USE_BIT not set then CB cannot already be executing 4164a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes // on device 41653251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= validateCommandBufferSimultaneousUse(dev_data, pCB, current_submit_count); 4166a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes 41673251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= validateResources(dev_data, pCB); 4168a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes 41695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!pCB->secondaryCommandBuffers.empty()) { 41705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto secondaryCmdBuffer : pCB->secondaryCommandBuffers) { 41719a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pSubCB = GetCBNode(dev_data, secondaryCmdBuffer); 41723251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= validateResources(dev_data, pSubCB); 41734c665b29a9d2906a378417546c7fc6436731d07fTobin Ehlis if ((pSubCB->primaryCommandBuffer != pCB->commandBuffer) && 41744c665b29a9d2906a378417546c7fc6436731d07fTobin Ehlis !(pSubCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT)) { 4175f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen log_msg( 4176f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, 4177f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen __LINE__, VALIDATION_ERROR_00135, "DS", 4178f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen "Commandbuffer 0x%p was submitted with secondary buffer 0x%p but that buffer has subsequently been bound to " 4179f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen "primary cmd buffer 0x%p and it does not have VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT set. %s", 4180f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen pCB->commandBuffer, secondaryCmdBuffer, pSubCB->primaryCommandBuffer, 4181f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen validation_error_map[VALIDATION_ERROR_00135]); 41825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 41835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 41845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 4185a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes 41863251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= validateCommandBufferState(dev_data, pCB, "vkQueueSubmit()", current_submit_count); 4187a2d08a743ac1178e4d46da4d41c73fb73b5e79d7Chris Forbes 41883251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 41895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 41905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4191bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic bool ValidateFenceForSubmit(layer_data *dev_data, FENCE_NODE *pFence) { 41923251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 419381c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes 4194651d92815dfff917308137bb67aacccc4f60df86Chris Forbes if (pFence) { 4195cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes if (pFence->state == FENCE_INFLIGHT) { 4196f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen // TODO: opportunities for VALIDATION_ERROR_00127, VALIDATION_ERROR_01647, VALIDATION_ERROR_01953 41973251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, 41983251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski (uint64_t)(pFence->fence), __LINE__, DRAWSTATE_INVALID_FENCE, "DS", 41993251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Fence 0x%" PRIx64 " is already in use by another submission.", (uint64_t)(pFence->fence)); 4200a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis } 420181c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes 4202cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes else if (pFence->state == FENCE_RETIRED) { 4203f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen // TODO: opportunities for VALIDATION_ERROR_00126, VALIDATION_ERROR_01646, VALIDATION_ERROR_01953 42043251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, 42053251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t &>(pFence->fence), __LINE__, MEMTRACK_INVALID_FENCE_STATE, "MEM", 42063251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Fence 0x%" PRIxLEAST64 " submitted in SIGNALED state. Fences must be reset before being submitted", 42073251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t &>(pFence->fence)); 4208a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis } 42095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 421081c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes 42113251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 421281c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes} 421381c4a32a622486043c15e427fb0e85cc1cf7dd47Chris Forbes 421451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourstatic void PostCallRecordQueueSubmit(layer_data *dev_data, VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, 421551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour VkFence fence) { 42169a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pQueue = GetQueueState(dev_data, queue); 42179a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pFence = GetFenceNode(dev_data, fence); 4218d7d60cccc862fee2d0b3ad410c5fdcc40ddc83aeChris Forbes 4219651d92815dfff917308137bb67aacccc4f60df86Chris Forbes // Mark the fence in-use. 4220651d92815dfff917308137bb67aacccc4f60df86Chris Forbes if (pFence) { 42219867daedbf52debc77d6568162ee21e071699b80Chris Forbes SubmitFence(pQueue, pFence, std::max(1u, submitCount)); 4222651d92815dfff917308137bb67aacccc4f60df86Chris Forbes } 4223651d92815dfff917308137bb67aacccc4f60df86Chris Forbes 422451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour // Now process each individual submit 42255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) { 422651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour std::vector<VkCommandBuffer> cbs; 42275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkSubmitInfo *submit = &pSubmits[submit_idx]; 42289867daedbf52debc77d6568162ee21e071699b80Chris Forbes vector<SEMAPHORE_WAIT> semaphore_waits; 42299867daedbf52debc77d6568162ee21e071699b80Chris Forbes vector<VkSemaphore> semaphore_signals; 42305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < submit->waitSemaphoreCount; ++i) { 423151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour VkSemaphore semaphore = submit->pWaitSemaphores[i]; 423251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour auto pSemaphore = GetSemaphoreNode(dev_data, semaphore); 423351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (pSemaphore) { 423451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (pSemaphore->signaler.first != VK_NULL_HANDLE) { 423551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour semaphore_waits.push_back({semaphore, pSemaphore->signaler.first, pSemaphore->signaler.second}); 423651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pSemaphore->in_use.fetch_add(1); 423751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 423851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pSemaphore->signaler.first = VK_NULL_HANDLE; 423951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pSemaphore->signaled = false; 424051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 424151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 424251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour for (uint32_t i = 0; i < submit->signalSemaphoreCount; ++i) { 424351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour VkSemaphore semaphore = submit->pSignalSemaphores[i]; 424451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour auto pSemaphore = GetSemaphoreNode(dev_data, semaphore); 424551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (pSemaphore) { 424651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pSemaphore->signaler.first = queue; 424751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pSemaphore->signaler.second = pQueue->seq + pQueue->submissions.size() + 1; 424851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pSemaphore->signaled = true; 424951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pSemaphore->in_use.fetch_add(1); 425051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour semaphore_signals.push_back(semaphore); 425151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 425251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 425351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour for (uint32_t i = 0; i < submit->commandBufferCount; i++) { 425451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour auto cb_node = GetCBNode(dev_data, submit->pCommandBuffers[i]); 425551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (cb_node) { 425651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour cbs.push_back(submit->pCommandBuffers[i]); 425751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour for (auto secondaryCmdBuffer : cb_node->secondaryCommandBuffers) { 425851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour cbs.push_back(secondaryCmdBuffer); 425951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 426051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour UpdateCmdBufImageLayouts(dev_data, cb_node); 426151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour incrementResources(dev_data, cb_node); 426251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (!cb_node->secondaryCommandBuffers.empty()) { 426351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour for (auto secondaryCmdBuffer : cb_node->secondaryCommandBuffers) { 426451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour GLOBAL_CB_NODE *pSubCB = GetCBNode(dev_data, secondaryCmdBuffer); 426551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour incrementResources(dev_data, pSubCB); 426651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 426751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 426851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 426951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 427051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pQueue->submissions.emplace_back(cbs, semaphore_waits, semaphore_signals, 427151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour submit_idx == submitCount - 1 ? fence : VK_NULL_HANDLE); 427251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 427351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 427451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (pFence && !submitCount) { 427551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour // If no submissions, but just dropping a fence on the end of the queue, 427651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour // record an empty submission with just the fence, so we can determine 427751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour // its completion. 427851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour pQueue->submissions.emplace_back(std::vector<VkCommandBuffer>(), std::vector<SEMAPHORE_WAIT>(), std::vector<VkSemaphore>(), 427951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour fence); 428051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 428151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour} 428251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 428351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbourstatic bool PreCallValidateQueueSubmit(layer_data *dev_data, VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, 428451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour VkFence fence) { 428551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour auto pFence = GetFenceNode(dev_data, fence); 42863251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = ValidateFenceForSubmit(dev_data, pFence); 42873251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (skip) { 428851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour return true; 428951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 429051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 429151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour unordered_set<VkSemaphore> signaled_semaphores; 429251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour unordered_set<VkSemaphore> unsignaled_semaphores; 429351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour vector<VkCommandBuffer> current_cmds; 429451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour unordered_map<ImageSubresourcePair, IMAGE_LAYOUT_NODE> localImageLayoutMap = dev_data->imageLayoutMap; 429551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour // Now verify each individual submit 429651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) { 429751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour const VkSubmitInfo *submit = &pSubmits[submit_idx]; 429851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour for (uint32_t i = 0; i < submit->waitSemaphoreCount; ++i) { 42993251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateStageMaskGsTsEnables(dev_data, submit->pWaitDstStageMask[i], "vkQueueSubmit()", VALIDATION_ERROR_00142, 43003251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski VALIDATION_ERROR_00143); 430101a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes VkSemaphore semaphore = submit->pWaitSemaphores[i]; 43029a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pSemaphore = GetSemaphoreNode(dev_data, semaphore); 430301a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes if (pSemaphore) { 430451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour if (unsignaled_semaphores.count(semaphore) || 4305440bdd357701497c3442e3515f12ac1cfffc180aTony Barbour (!(signaled_semaphores.count(semaphore)) && !(pSemaphore->signaled))) { 43063251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT, 43073251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<const uint64_t &>(semaphore), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS", 43083251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Queue 0x%p is waiting on semaphore 0x%" PRIx64 " that has no way to be signaled.", queue, 43093251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<const uint64_t &>(semaphore)); 431051920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } else { 431151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour signaled_semaphores.erase(semaphore); 431251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour unsignaled_semaphores.insert(semaphore); 43131344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis } 43145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 43155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 43165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < submit->signalSemaphoreCount; ++i) { 431701a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes VkSemaphore semaphore = submit->pSignalSemaphores[i]; 43189a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pSemaphore = GetSemaphoreNode(dev_data, semaphore); 431901a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes if (pSemaphore) { 4320440bdd357701497c3442e3515f12ac1cfffc180aTony Barbour if (signaled_semaphores.count(semaphore) || (!(unsignaled_semaphores.count(semaphore)) && pSemaphore->signaled)) { 43213251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT, 43223251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<const uint64_t &>(semaphore), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS", 43233251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Queue 0x%p is signaling semaphore 0x%" PRIx64 43243251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski " that has already been signaled but not waited on by queue 0x%" PRIx64 ".", 43253251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski queue, reinterpret_cast<const uint64_t &>(semaphore), 43263251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t &>(pSemaphore->signaler.first)); 43271344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis } else { 432851920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour unsignaled_semaphores.erase(semaphore); 432951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour signaled_semaphores.insert(semaphore); 43301344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis } 43310a32ed7bdf03e7bda914e03c0bfa6ebf400cdf5bMichael Lentine } 43325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 43335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < submit->commandBufferCount; i++) { 43349a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, submit->pCommandBuffers[i]); 4335d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis if (cb_node) { 43363251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmdBufImageLayouts(dev_data, cb_node, localImageLayoutMap); 433751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour current_cmds.push_back(submit->pCommandBuffers[i]); 43383251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= validatePrimaryCommandBufferState( 433951920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour dev_data, cb_node, (int)std::count(current_cmds.begin(), current_cmds.end(), submit->pCommandBuffers[i])); 43403251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= validateQueueFamilyIndices(dev_data, cb_node, queue); 434151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 4342ea371fa7c8c57edb4d1436e4570cf54f3fc0463fTobin Ehlis // Potential early exit here as bad object state may crash in delayed function calls 43433251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (skip) { 434451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour return true; 434551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour } 434651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 43471344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis // Call submit-time functions to validate/update state 4348d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis for (auto &function : cb_node->validate_functions) { 43493251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= function(); 43501344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis } 4351d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis for (auto &function : cb_node->eventUpdates) { 43523251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= function(queue); 43531344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis } 4354d74f8771414d9e80618cd7604ea4b1c459dfa42eTobin Ehlis for (auto &function : cb_node->queryUpdates) { 43553251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= function(queue); 4356d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 43571344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis } 43585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 43599867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 43603251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 436151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour} 43629867daedbf52debc77d6568162ee21e071699b80Chris Forbes 436351920949f887ce8d3666c73c28ff19a5d8325a37Tony BarbourVKAPI_ATTR VkResult VKAPI_CALL QueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence) { 436451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map); 436551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour std::unique_lock<std::mutex> lock(global_lock); 436651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 436751920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour bool skip = PreCallValidateQueueSubmit(dev_data, queue, submitCount, pSubmits, fence); 4368b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 43695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4370440bdd357701497c3442e3515f12ac1cfffc180aTony Barbour if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 437151920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 437251920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour VkResult result = dev_data->dispatch_table.QueueSubmit(queue, submitCount, pSubmits, fence); 437351920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour 437451920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour lock.lock(); 437551920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour PostCallRecordQueueSubmit(dev_data, queue, submitCount, pSubmits, fence); 437651920949f887ce8d3666c73c28ff19a5d8325a37Tony Barbour lock.unlock(); 43775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 43785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 43795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4380f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultzstatic bool PreCallValidateAllocateMemory(layer_data *dev_data) { 4381f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz bool skip = false; 4382f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz if (dev_data->memObjMap.size() >= dev_data->phys_dev_properties.properties.limits.maxMemoryAllocationCount) { 4383f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 4384f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz reinterpret_cast<const uint64_t &>(dev_data->device), __LINE__, VALIDATION_ERROR_00611, "MEM", 4385f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz "Number of currently valid memory objects is not less than the maximum allowed (%u). %s", 4386f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz dev_data->phys_dev_properties.properties.limits.maxMemoryAllocationCount, 4387f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz validation_error_map[VALIDATION_ERROR_00611]); 4388f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz } 4389f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz return skip; 4390f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz} 4391f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz 4392f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultzstatic void PostCallRecordAllocateMemory(layer_data *dev_data, const VkMemoryAllocateInfo *pAllocateInfo, VkDeviceMemory *pMemory) { 4393f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz add_mem_obj_info(dev_data, dev_data->device, *pMemory, pAllocateInfo); 4394f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz return; 4395f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz} 4396f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz 439789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL AllocateMemory(VkDevice device, const VkMemoryAllocateInfo *pAllocateInfo, 439889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkDeviceMemory *pMemory) { 4399f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 440056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 4401f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz std::unique_lock<std::mutex> lock(global_lock); 4402f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz bool skip = PreCallValidateAllocateMemory(dev_data); 4403f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz if (!skip) { 4404f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz lock.unlock(); 4405f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz result = dev_data->dispatch_table.AllocateMemory(device, pAllocateInfo, pAllocator, pMemory); 4406f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz lock.lock(); 4407f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz if (VK_SUCCESS == result) { 4408f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz PostCallRecordAllocateMemory(dev_data, pAllocateInfo, pMemory); 4409f9e31fcaf5f4630e1bf38870a6457e1a04b4a486Karl Schultz } 4410e12739a56d02ca2fb5f0273862668e7475a21a6cMark Lobodzinski } 44115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 44125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 44135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4414177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis// For given obj node, if it is use, flag a validation error and return callback result, else return false 4415177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlisbool ValidateObjectNotInUse(const layer_data *dev_data, BASE_NODE *obj_node, VK_OBJECT obj_struct, 4416177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis UNIQUE_VALIDATION_ERROR_CODE error_code) { 4417cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.object_in_use) return false; 4418177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis bool skip = false; 4419177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis if (obj_node->in_use.load()) { 44207a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski skip |= 442102a510945ff39f3d9e486e456aca5bfa6ea0c43aMark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, get_debug_report_enum[obj_struct.type], obj_struct.handle, 44227a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski __LINE__, error_code, "DS", "Cannot delete %s 0x%" PRIx64 " that is currently in use by a command buffer. %s", 44237a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski object_string[obj_struct.type], obj_struct.handle, validation_error_map[error_code]); 4424177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis } 4425177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis return skip; 4426177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis} 44275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4428177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlisstatic bool PreCallValidateFreeMemory(layer_data *dev_data, VkDeviceMemory mem, DEVICE_MEM_INFO **mem_info, VK_OBJECT *obj_struct) { 44299a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *mem_info = GetMemObjInfo(dev_data, mem); 44307a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski *obj_struct = {reinterpret_cast<uint64_t &>(mem), kVulkanObjectTypeDeviceMemory}; 4431cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.free_memory) return false; 4432177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis bool skip = false; 4433177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis if (*mem_info) { 4434177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis skip |= ValidateObjectNotInUse(dev_data, *mem_info, *obj_struct, VALIDATION_ERROR_00620); 4435177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis } 4436177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis return skip; 4437177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis} 44385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4439177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlisstatic void PostCallRecordFreeMemory(layer_data *dev_data, VkDeviceMemory mem, DEVICE_MEM_INFO *mem_info, VK_OBJECT obj_struct) { 4440177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis // Clear mem binding for any bound objects 444147705d01140c9f1492885e6efc5fa262e7e1c6a0Tobin Ehlis for (auto obj : mem_info->obj_bindings) { 444202a510945ff39f3d9e486e456aca5bfa6ea0c43aMark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, get_debug_report_enum[obj.type], obj.handle, __LINE__, 44437a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski MEMTRACK_FREED_MEM_REF, "MEM", "VK Object 0x%" PRIxLEAST64 " still has a reference to mem obj 0x%" PRIxLEAST64, 44447a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski obj.handle, (uint64_t)mem_info->mem); 444547705d01140c9f1492885e6efc5fa262e7e1c6a0Tobin Ehlis switch (obj.type) { 44467a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski case kVulkanObjectTypeImage: { 44479a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_state = GetImageState(dev_data, reinterpret_cast<VkImage &>(obj.handle)); 4448cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski assert(image_state); // Any destroyed images should already be removed from bindings 4449cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski image_state->binding.mem = MEMORY_UNBOUND; 4450cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 4451cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 44527a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski case kVulkanObjectTypeBuffer: { 44539a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto buffer_state = GetBufferState(dev_data, reinterpret_cast<VkBuffer &>(obj.handle)); 4454cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski assert(buffer_state); // Any destroyed buffers should already be removed from bindings 4455cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski buffer_state->binding.mem = MEMORY_UNBOUND; 4456cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 4457cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 4458cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 4459cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Should only have buffer or image objects bound to memory 4460cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski assert(0); 4461177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis } 4462177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis } 4463177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis // Any bound cmd buffers are now invalid 446439c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis invalidateCommandBuffers(dev_data, mem_info->cb_bindings, obj_struct); 4465177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis dev_data->memObjMap.erase(mem); 4466177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis} 4467177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis 4468177063aac84fac6f4e650c2629a08b48be643f96Tobin EhlisVKAPI_ATTR void VKAPI_CALL FreeMemory(VkDevice device, VkDeviceMemory mem, const VkAllocationCallbacks *pAllocator) { 446956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 4470177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis DEVICE_MEM_INFO *mem_info = nullptr; 4471177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis VK_OBJECT obj_struct; 4472b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 4473177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis bool skip = PreCallValidateFreeMemory(dev_data, mem, &mem_info, &obj_struct); 4474177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis if (!skip) { 4475177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis lock.unlock(); 4476177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis dev_data->dispatch_table.FreeMemory(device, mem, pAllocator); 4477177063aac84fac6f4e650c2629a08b48be643f96Tobin Ehlis lock.lock(); 4478405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (mem != VK_NULL_HANDLE) { 4479405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordFreeMemory(dev_data, mem, mem_info, obj_struct); 4480405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 448174243a735fe102b370237ddf80d3e6f7ec5246dbMark Mueller } 44825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 44835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4484f57fc64ac43691ad98e1713886b345465573070aTobin Ehlis// Validate that given Map memory range is valid. This means that the memory should not already be mapped, 4485f57fc64ac43691ad98e1713886b345465573070aTobin Ehlis// and that the size of the map range should be: 4486f57fc64ac43691ad98e1713886b345465573070aTobin Ehlis// 1. Not zero 4487f57fc64ac43691ad98e1713886b345465573070aTobin Ehlis// 2. Within the size of the memory allocation 448851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool ValidateMapMemRange(layer_data *dev_data, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size) { 44893251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 44905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 44915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (size == 0) { 44923251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 44933251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski (uint64_t)mem, __LINE__, MEMTRACK_INVALID_MAP, "MEM", 44943251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "VkMapMemory: Attempting to map memory range of size zero"); 44955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 44965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 449751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis auto mem_element = dev_data->memObjMap.find(mem); 449851ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis if (mem_element != dev_data->memObjMap.end()) { 449957fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis auto mem_info = mem_element->second.get(); 45005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // It is an application error to call VkMapMemory on an object that is already mapped 4501de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis if (mem_info->mem_range.size != 0) { 45023251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 45033251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski (uint64_t)mem, __LINE__, MEMTRACK_INVALID_MAP, "MEM", 45043251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "VkMapMemory: Attempting to map memory on an already-mapped object 0x%" PRIxLEAST64, (uint64_t)mem); 45055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 45065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 45075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Validate that offset + size is within object's allocationSize 45085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (size == VK_WHOLE_SIZE) { 4509de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis if (offset >= mem_info->alloc_info.allocationSize) { 45103251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 45113251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski (uint64_t)mem, __LINE__, MEMTRACK_INVALID_MAP, "MEM", 45123251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Mapping Memory from 0x%" PRIx64 " to 0x%" PRIx64 45133251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski " with size of VK_WHOLE_SIZE oversteps total array size 0x%" PRIx64, 45143251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski offset, mem_info->alloc_info.allocationSize, mem_info->alloc_info.allocationSize); 45155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 45165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 4517de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis if ((offset + size) > mem_info->alloc_info.allocationSize) { 45183251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 45193251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski (uint64_t)mem, __LINE__, VALIDATION_ERROR_00628, "MEM", 45203251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Mapping Memory from 0x%" PRIx64 " to 0x%" PRIx64 " oversteps total array size 0x%" PRIx64 ". %s", 45213251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski offset, size + offset, mem_info->alloc_info.allocationSize, 45223251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski validation_error_map[VALIDATION_ERROR_00628]); 45235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 45245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 45255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 45263251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 45275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 45285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 452951ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic void storeMemRanges(layer_data *dev_data, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size) { 45309a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto mem_info = GetMemObjInfo(dev_data, mem); 453157fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis if (mem_info) { 4532de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis mem_info->mem_range.offset = offset; 4533de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis mem_info->mem_range.size = size; 45345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 45355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 45365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 453751ea774638f432bd8e700ec8291a980f405f429eTobin Ehlisstatic bool deleteMemRanges(layer_data *dev_data, VkDeviceMemory mem) { 45383251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 45399a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto mem_info = GetMemObjInfo(dev_data, mem); 454057fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis if (mem_info) { 4541de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis if (!mem_info->mem_range.size) { 45425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Valid Usage: memory must currently be mapped 45433251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 45443251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski (uint64_t)mem, __LINE__, VALIDATION_ERROR_00649, "MEM", 45453251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Unmapping Memory without memory being mapped: mem obj 0x%" PRIxLEAST64 ". %s", (uint64_t)mem, 45463251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski validation_error_map[VALIDATION_ERROR_00649]); 45475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 4548de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis mem_info->mem_range.size = 0; 45495f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski if (mem_info->shadow_copy) { 45505f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski free(mem_info->shadow_copy_base); 45515f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski mem_info->shadow_copy_base = 0; 45525f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski mem_info->shadow_copy = 0; 45535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 45545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 45553251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 45565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 45575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 45585f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski// Guard value for pad data 45595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisstatic char NoncoherentMemoryFillValue = 0xb; 45605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 45615f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinskistatic void initializeAndTrackMemory(layer_data *dev_data, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size, 45625f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski void **ppData) { 45639a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto mem_info = GetMemObjInfo(dev_data, mem); 456457fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis if (mem_info) { 4565de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis mem_info->p_driver_data = *ppData; 4566de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis uint32_t index = mem_info->alloc_info.memoryTypeIndex; 4567b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis if (dev_data->phys_dev_mem_props.memoryTypes[index].propertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) { 45685f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski mem_info->shadow_copy = 0; 45695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 45705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (size == VK_WHOLE_SIZE) { 45715f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski size = mem_info->alloc_info.allocationSize - offset; 45725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 45735f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski mem_info->shadow_pad_size = dev_data->phys_dev_properties.properties.limits.minMemoryMapAlignment; 457416769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton assert(SafeModulo(mem_info->shadow_pad_size, 45755f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski dev_data->phys_dev_properties.properties.limits.minMemoryMapAlignment) == 0); 45765f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski // Ensure start of mapped region reflects hardware alignment constraints 45775f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski uint64_t map_alignment = dev_data->phys_dev_properties.properties.limits.minMemoryMapAlignment; 45785f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski 45795f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski // From spec: (ppData - offset) must be aligned to at least limits::minMemoryMapAlignment. 45805f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski uint64_t start_offset = offset % map_alignment; 45815f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski // Data passed to driver will be wrapped by a guardband of data to detect over- or under-writes. 4582bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski mem_info->shadow_copy_base = 4583bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski malloc(static_cast<size_t>(2 * mem_info->shadow_pad_size + size + map_alignment + start_offset)); 45845f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski 45855f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski mem_info->shadow_copy = 45865f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski reinterpret_cast<char *>((reinterpret_cast<uintptr_t>(mem_info->shadow_copy_base) + map_alignment) & 4587bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski ~(map_alignment - 1)) + 4588bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski start_offset; 458916769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton assert(SafeModulo(reinterpret_cast<uintptr_t>(mem_info->shadow_copy) + mem_info->shadow_pad_size - start_offset, 45905f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski map_alignment) == 0); 45915f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski 45926e17c244b21ce43ac57404a00a0d844039eed363Mark Lobodzinski memset(mem_info->shadow_copy, NoncoherentMemoryFillValue, static_cast<size_t>(2 * mem_info->shadow_pad_size + size)); 45935f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski *ppData = static_cast<char *>(mem_info->shadow_copy) + mem_info->shadow_pad_size; 45945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 45955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 45965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 45975f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski 4598a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis// Verify that state for fence being waited on is appropriate. That is, 45999867daedbf52debc77d6568162ee21e071699b80Chris Forbes// a fence being waited on should not already be signaled and 4600a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis// it should have been submitted on a queue or during acquire next image 460149f6132af865afd5b7f413c91125971ac97c135aChris Forbesstatic inline bool verifyWaitFenceState(layer_data *dev_data, VkFence fence, const char *apiCall) { 46023251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 46039b48b44dd917f95b5f34dd629ec4076fc87eb3a2Chris Forbes 46049a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pFence = GetFenceNode(dev_data, fence); 46059b48b44dd917f95b5f34dd629ec4076fc87eb3a2Chris Forbes if (pFence) { 4606cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes if (pFence->state == FENCE_UNSIGNALED) { 46073251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, 46083251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t &>(fence), __LINE__, MEMTRACK_INVALID_FENCE_STATE, "MEM", 46093251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "%s called for fence 0x%" PRIxLEAST64 46103251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski " which has not been submitted on a Queue or during " 46113251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "acquire next image.", 46123251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski apiCall, reinterpret_cast<uint64_t &>(fence)); 46135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 46145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 46153251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 46165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 4617a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis 4618b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlisstatic void RetireFence(layer_data *dev_data, VkFence fence) { 46199a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pFence = GetFenceNode(dev_data, fence); 4620b3ecd4c1fb44a2e65dfc13256afa9150aabde1d4Chris Forbes if (pFence->signaler.first != VK_NULL_HANDLE) { 462125002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Fence signaller is a queue -- use this as proof that prior operations on that queue have completed. 46229a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis RetireWorkOnQueue(dev_data, GetQueueState(dev_data, pFence->signaler.first), pFence->signaler.second); 4623bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski } else { 462425002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // Fence signaller is the WSI. We're not tracking what the WSI op actually /was/ in CV yet, but we need to mark 462525002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // the fence as retired. 4626d4513979120463171eb479cdded9336eb9944da1Chris Forbes pFence->state = FENCE_RETIRED; 4627d4513979120463171eb479cdded9336eb9944da1Chris Forbes } 4628b3ecd4c1fb44a2e65dfc13256afa9150aabde1d4Chris Forbes} 4629b3ecd4c1fb44a2e65dfc13256afa9150aabde1d4Chris Forbes 4630accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlisstatic bool PreCallValidateWaitForFences(layer_data *dev_data, uint32_t fence_count, const VkFence *fences) { 4631cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.wait_for_fences) return false; 4632accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis bool skip = false; 4633accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis for (uint32_t i = 0; i < fence_count; i++) { 4634accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis skip |= verifyWaitFenceState(dev_data, fences[i], "vkWaitForFences"); 4635b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis skip |= VerifyQueueStateToFence(dev_data, fences[i]); 4636accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis } 4637accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis return skip; 4638accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis} 4639accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis 4640b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlisstatic void PostCallRecordWaitForFences(layer_data *dev_data, uint32_t fence_count, const VkFence *fences, VkBool32 wait_all) { 4641b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis // When we know that all fences are complete we can clean/remove their CBs 4642accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis if ((VK_TRUE == wait_all) || (1 == fence_count)) { 4643accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis for (uint32_t i = 0; i < fence_count; i++) { 4644b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis RetireFence(dev_data, fences[i]); 4645accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis } 4646accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis } 4647accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis // NOTE : Alternate case not handled here is when some fences have completed. In 4648accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis // this case for app to guarantee which fences completed it will have to call 4649b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis // vkGetFenceStatus() at which point we'll clean/remove their CBs if complete. 4650accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis} 4651accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis 4652bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL WaitForFences(VkDevice device, uint32_t fenceCount, const VkFence *pFences, VkBool32 waitAll, 4653bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski uint64_t timeout) { 465456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 46555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Verify fence status of submitted fences 4656b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 4657accdf1d467e269e05b89764faf204fb2ff600b57Tobin Ehlis bool skip = PreCallValidateWaitForFences(dev_data, fenceCount, pFences); 4658b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 4659cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 4660a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis 46614a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.WaitForFences(device, fenceCount, pFences, waitAll, timeout); 4662414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller 46635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (result == VK_SUCCESS) { 4664b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.lock(); 4665b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis PostCallRecordWaitForFences(dev_data, fenceCount, pFences, waitAll); 4666b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 46675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 46685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 46695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 46705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4671f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlisstatic bool PreCallValidateGetFenceStatus(layer_data *dev_data, VkFence fence) { 4672cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.get_fence_state) return false; 4673f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis return verifyWaitFenceState(dev_data, fence, "vkGetFenceStatus"); 4674f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis} 4675f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis 4676b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlisstatic void PostCallRecordGetFenceStatus(layer_data *dev_data, VkFence fence) { RetireFence(dev_data, fence); } 4677f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis 467889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL GetFenceStatus(VkDevice device, VkFence fence) { 467956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 4680b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 4681f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis bool skip = PreCallValidateGetFenceStatus(dev_data, fence); 4682b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 4683cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 4684a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis 46854a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.GetFenceStatus(device, fence); 46865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (result == VK_SUCCESS) { 4687f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis lock.lock(); 4688b7d814f72a72fb2eee7efa0f48e6a67a86eaf588Tobin Ehlis PostCallRecordGetFenceStatus(dev_data, fence); 4689f073b96e7a0030b55a66b780bd3ed57262cf1fa2Tobin Ehlis lock.unlock(); 46905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 46915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 46925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 46935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 46943b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlisstatic void PostCallRecordGetDeviceQueue(layer_data *dev_data, uint32_t q_family_index, VkQueue queue) { 46953b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis // Add queue to tracking set only if it is new 46963b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis auto result = dev_data->queues.emplace(queue); 46973b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis if (result.second == true) { 469836c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlis QUEUE_STATE *queue_state = &dev_data->queueMap[queue]; 46993b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis queue_state->queue = queue; 47003b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis queue_state->queueFamilyIndex = q_family_index; 47013b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis queue_state->seq = 0; 47023b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis } 47033b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis} 47043b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis 4705bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL GetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue *pQueue) { 470656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 47074a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue); 4708b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 4709b376edacad6f7ab3fcc0a914e9b1673a9fcd5143Mark Lobodzinski 47103b3fccc991a6cbe649b96880f36d90318b3c7cc2Tobin Ehlis PostCallRecordGetDeviceQueue(dev_data, queueFamilyIndex, *pQueue); 47115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 47125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 471336c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlisstatic bool PreCallValidateQueueWaitIdle(layer_data *dev_data, VkQueue queue, QUEUE_STATE **queue_state) { 47149a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *queue_state = GetQueueState(dev_data, queue); 4715cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.queue_wait_idle) return false; 4716e0cec9ec6dd3cfd83345cabba55ec021681801dbTobin Ehlis return VerifyQueueStateToSeq(dev_data, *queue_state, (*queue_state)->seq + (*queue_state)->submissions.size()); 47174273a1c157585a645dca4c960086032793899d05Tobin Ehlis} 47184273a1c157585a645dca4c960086032793899d05Tobin Ehlis 471936c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlisstatic void PostCallRecordQueueWaitIdle(layer_data *dev_data, QUEUE_STATE *queue_state) { 4720e0cec9ec6dd3cfd83345cabba55ec021681801dbTobin Ehlis RetireWorkOnQueue(dev_data, queue_state, queue_state->seq + queue_state->submissions.size()); 47214273a1c157585a645dca4c960086032793899d05Tobin Ehlis} 47224273a1c157585a645dca4c960086032793899d05Tobin Ehlis 472389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL QueueWaitIdle(VkQueue queue) { 472456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map); 472536c3a4fe8455762d2dc0b2b9ece44675a3ee8d97Tobin Ehlis QUEUE_STATE *queue_state = nullptr; 47269867daedbf52debc77d6568162ee21e071699b80Chris Forbes std::unique_lock<std::mutex> lock(global_lock); 47274273a1c157585a645dca4c960086032793899d05Tobin Ehlis bool skip = PreCallValidateQueueWaitIdle(dev_data, queue, &queue_state); 47289867daedbf52debc77d6568162ee21e071699b80Chris Forbes lock.unlock(); 4729cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 47304a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.QueueWaitIdle(queue); 47314273a1c157585a645dca4c960086032793899d05Tobin Ehlis if (VK_SUCCESS == result) { 4732e0cec9ec6dd3cfd83345cabba55ec021681801dbTobin Ehlis lock.lock(); 4733e0cec9ec6dd3cfd83345cabba55ec021681801dbTobin Ehlis PostCallRecordQueueWaitIdle(dev_data, queue_state); 4734e0cec9ec6dd3cfd83345cabba55ec021681801dbTobin Ehlis lock.unlock(); 47354273a1c157585a645dca4c960086032793899d05Tobin Ehlis } 47365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 47375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 47385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 47398767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlisstatic bool PreCallValidateDeviceWaitIdle(layer_data *dev_data) { 4740cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.device_wait_idle) return false; 47418767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis bool skip = false; 47428767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis for (auto &queue : dev_data->queueMap) { 47438767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis skip |= VerifyQueueStateToSeq(dev_data, &queue.second, queue.second.seq + queue.second.submissions.size()); 47448767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis } 47458767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis return skip; 47468767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis} 47478767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis 47488767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlisstatic void PostCallRecordDeviceWaitIdle(layer_data *dev_data) { 47498767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis for (auto &queue : dev_data->queueMap) { 47508767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis RetireWorkOnQueue(dev_data, &queue.second, queue.second.seq + queue.second.submissions.size()); 47518767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis } 47528767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis} 47538767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis 475489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL DeviceWaitIdle(VkDevice device) { 475556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 4756b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 47578767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis bool skip = PreCallValidateDeviceWaitIdle(dev_data); 4758b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 4759cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 47604a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.DeviceWaitIdle(device); 47618767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis if (VK_SUCCESS == result) { 47628767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis lock.lock(); 47638767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis PostCallRecordDeviceWaitIdle(dev_data); 47648767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis lock.unlock(); 47658767ceaf6a7d5675c2fe0502df31a1339a5a6337Tobin Ehlis } 47665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 47675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 47685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 47691d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlisstatic bool PreCallValidateDestroyFence(layer_data *dev_data, VkFence fence, FENCE_NODE **fence_node, VK_OBJECT *obj_struct) { 47709a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *fence_node = GetFenceNode(dev_data, fence); 47717a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski *obj_struct = {reinterpret_cast<uint64_t &>(fence), kVulkanObjectTypeFence}; 4772cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_fence) return false; 47731d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis bool skip = false; 47741d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis if (*fence_node) { 47751d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis if ((*fence_node)->state == FENCE_INFLIGHT) { 47761d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, 4777208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis (uint64_t)(fence), __LINE__, VALIDATION_ERROR_00173, "DS", "Fence 0x%" PRIx64 " is in use. %s", 4778208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis (uint64_t)(fence), validation_error_map[VALIDATION_ERROR_00173]); 47791d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis } 47801d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis } 47811d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis return skip; 47821d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis} 47831d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis 47841d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlisstatic void PostCallRecordDestroyFence(layer_data *dev_data, VkFence fence) { dev_data->fenceMap.erase(fence); } 47851d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis 478689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL DestroyFence(VkDevice device, VkFence fence, const VkAllocationCallbacks *pAllocator) { 478756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 47881d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis // Common data objects used pre & post call 47891d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis FENCE_NODE *fence_node = nullptr; 47901d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis VK_OBJECT obj_struct; 4791b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 47921d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis bool skip = PreCallValidateDestroyFence(dev_data, fence, &fence_node, &obj_struct); 47931344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis 47941d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis if (!skip) { 47951d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis lock.unlock(); 47964a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyFence(device, fence, pAllocator); 47971d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis lock.lock(); 47981d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis PostCallRecordDestroyFence(dev_data, fence); 47991d3dce01906e45faf7282cffc3334cbda1662656Tobin Ehlis } 48005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 48015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4802c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlisstatic bool PreCallValidateDestroySemaphore(layer_data *dev_data, VkSemaphore semaphore, SEMAPHORE_NODE **sema_node, 4803c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis VK_OBJECT *obj_struct) { 48049a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *sema_node = GetSemaphoreNode(dev_data, semaphore); 48057a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski *obj_struct = {reinterpret_cast<uint64_t &>(semaphore), kVulkanObjectTypeSemaphore}; 4806cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_semaphore) return false; 4807c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis bool skip = false; 4808c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis if (*sema_node) { 4809c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis skip |= ValidateObjectNotInUse(dev_data, *sema_node, *obj_struct, VALIDATION_ERROR_00199); 4810c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis } 4811c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis return skip; 4812c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis} 4813c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis 4814c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlisstatic void PostCallRecordDestroySemaphore(layer_data *dev_data, VkSemaphore sema) { dev_data->semaphoreMap.erase(sema); } 4815c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis 4816bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroySemaphore(VkDevice device, VkSemaphore semaphore, const VkAllocationCallbacks *pAllocator) { 481756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 4818c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis SEMAPHORE_NODE *sema_node; 4819c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis VK_OBJECT obj_struct; 4820e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 4821c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis bool skip = PreCallValidateDestroySemaphore(dev_data, semaphore, &sema_node, &obj_struct); 4822eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis if (!skip) { 4823eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis lock.unlock(); 48244a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroySemaphore(device, semaphore, pAllocator); 4825c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis lock.lock(); 4826c0f1f8368ec7be6f098e2599b31622f81ff00185Tobin Ehlis PostCallRecordDestroySemaphore(dev_data, semaphore); 482799d938c90c2f000ee73fb13513dacf84ffa5651fMark Mueller } 48285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 48295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 48304710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlisstatic bool PreCallValidateDestroyEvent(layer_data *dev_data, VkEvent event, EVENT_STATE **event_state, VK_OBJECT *obj_struct) { 48319a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *event_state = GetEventNode(dev_data, event); 48327a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski *obj_struct = {reinterpret_cast<uint64_t &>(event), kVulkanObjectTypeEvent}; 4833cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_event) return false; 4834d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis bool skip = false; 4835d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis if (*event_state) { 4836d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis skip |= ValidateObjectNotInUse(dev_data, *event_state, *obj_struct, VALIDATION_ERROR_00213); 4837d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis } 4838d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis return skip; 4839d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis} 4840d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis 48414710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlisstatic void PostCallRecordDestroyEvent(layer_data *dev_data, VkEvent event, EVENT_STATE *event_state, VK_OBJECT obj_struct) { 484239c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis invalidateCommandBuffers(dev_data, event_state->cb_bindings, obj_struct); 4843d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis dev_data->eventMap.erase(event); 4844d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis} 4845d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis 484689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL DestroyEvent(VkDevice device, VkEvent event, const VkAllocationCallbacks *pAllocator) { 484756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 48484710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis EVENT_STATE *event_state = nullptr; 4849d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis VK_OBJECT obj_struct; 4850b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 4851d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis bool skip = PreCallValidateDestroyEvent(dev_data, event, &event_state, &obj_struct); 4852f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis if (!skip) { 4853f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis lock.unlock(); 48544a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyEvent(device, event, pAllocator); 4855d379c77e4254a740aa838a82e7af186525524617Tobin Ehlis lock.lock(); 4856405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (event != VK_NULL_HANDLE) { 4857405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyEvent(dev_data, event, event_state, obj_struct); 4858405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 4859f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis } 48605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 48615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 486283c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlisstatic bool PreCallValidateDestroyQueryPool(layer_data *dev_data, VkQueryPool query_pool, QUERY_POOL_NODE **qp_state, 486383c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis VK_OBJECT *obj_struct) { 48649a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *qp_state = GetQueryPoolNode(dev_data, query_pool); 48657a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski *obj_struct = {reinterpret_cast<uint64_t &>(query_pool), kVulkanObjectTypeQueryPool}; 4866cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_query_pool) return false; 486783c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis bool skip = false; 486883c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis if (*qp_state) { 486983c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis skip |= ValidateObjectNotInUse(dev_data, *qp_state, *obj_struct, VALIDATION_ERROR_01012); 487083c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis } 487183c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis return skip; 487283c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis} 487383c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis 4874bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic void PostCallRecordDestroyQueryPool(layer_data *dev_data, VkQueryPool query_pool, QUERY_POOL_NODE *qp_state, 4875bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VK_OBJECT obj_struct) { 487683c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis invalidateCommandBuffers(dev_data, qp_state->cb_bindings, obj_struct); 487783c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis dev_data->queryPoolMap.erase(query_pool); 487883c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis} 487983c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis 4880bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyQueryPool(VkDevice device, VkQueryPool queryPool, const VkAllocationCallbacks *pAllocator) { 488156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 488283c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis QUERY_POOL_NODE *qp_state = nullptr; 488383c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis VK_OBJECT obj_struct; 4884ccdcc9686c664e9407dd03262f3aaf3245b23be2Tobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 488583c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis bool skip = PreCallValidateDestroyQueryPool(dev_data, queryPool, &qp_state, &obj_struct); 4886f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis if (!skip) { 4887f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis lock.unlock(); 48884a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyQueryPool(device, queryPool, pAllocator); 488983c1f2cdfb8eca95c7d450aca7863d5b269b7be6Tobin Ehlis lock.lock(); 4890405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (queryPool != VK_NULL_HANDLE) { 4891405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyQueryPool(dev_data, queryPool, qp_state, obj_struct); 4892405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 4893f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis } 48945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 48959fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlisstatic bool PreCallValidateGetQueryPoolResults(layer_data *dev_data, VkQueryPool query_pool, uint32_t first_query, 48969fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis uint32_t query_count, VkQueryResultFlags flags, 48979fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis unordered_map<QueryObject, vector<VkCommandBuffer>> *queries_in_flight) { 48989fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis for (auto cmd_buffer : dev_data->globalInFlightCmdBuffers) { 48999a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb = GetCBNode(dev_data, cmd_buffer); 49009fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis for (auto query_state_pair : cb->queryToStateMap) { 49019fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis (*queries_in_flight)[query_state_pair.first].push_back(cmd_buffer); 49025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 49035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 4904cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.get_query_pool_results) return false; 49059fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis bool skip = false; 49069fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis for (uint32_t i = 0; i < query_count; ++i) { 49079fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis QueryObject query = {query_pool, first_query + i}; 49089fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis auto qif_pair = queries_in_flight->find(query); 49099fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis auto query_state_pair = dev_data->queryToStateMap.find(query); 49109fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis if (query_state_pair != dev_data->queryToStateMap.end()) { 4911ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski // Available and in flight 49129fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis if (qif_pair != queries_in_flight->end() && query_state_pair != dev_data->queryToStateMap.end() && 49139fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis query_state_pair->second) { 49149fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis for (auto cmd_buffer : qif_pair->second) { 49159a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb = GetCBNode(dev_data, cmd_buffer); 49169fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis auto query_event_pair = cb->waitedEventsBeforeQueryReset.find(query); 49179fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis if (query_event_pair == cb->waitedEventsBeforeQueryReset.end()) { 49189fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 49199fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, __LINE__, DRAWSTATE_INVALID_QUERY, "DS", 49209fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis "Cannot get query results on queryPool 0x%" PRIx64 " with index %d which is in flight.", 49219fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis (uint64_t)(query_pool), first_query + i); 4922ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski } 4923ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski } 4924ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski // Unavailable and in flight 49259fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis } else if (qif_pair != queries_in_flight->end() && query_state_pair != dev_data->queryToStateMap.end() && 49269fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis !query_state_pair->second) { 4927ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski // TODO : Can there be the same query in use by multiple command buffers in flight? 4928ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski bool make_available = false; 49299fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis for (auto cmd_buffer : qif_pair->second) { 49309a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb = GetCBNode(dev_data, cmd_buffer); 49319fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis make_available |= cb->queryToStateMap[query]; 4932ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski } 4933ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski if (!(((flags & VK_QUERY_RESULT_PARTIAL_BIT) || (flags & VK_QUERY_RESULT_WAIT_BIT)) && make_available)) { 49349fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 49359fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, __LINE__, DRAWSTATE_INVALID_QUERY, "DS", 49369fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis "Cannot get query results on queryPool 0x%" PRIx64 " with index %d which is unavailable.", 49379fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis (uint64_t)(query_pool), first_query + i); 49385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 4939ec27ab7d1aa03fa187755b6720e1be995a994f5cMark Lobodzinski // Unavailable 49409fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis } else if (query_state_pair != dev_data->queryToStateMap.end() && !query_state_pair->second) { 49419fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, 49429fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis __LINE__, DRAWSTATE_INVALID_QUERY, "DS", 49439fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis "Cannot get query results on queryPool 0x%" PRIx64 " with index %d which is unavailable.", 49449fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis (uint64_t)(query_pool), first_query + i); 49459fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis // Uninitialized 49469fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis } else if (query_state_pair == dev_data->queryToStateMap.end()) { 49479fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, 49489fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis __LINE__, DRAWSTATE_INVALID_QUERY, "DS", 49499fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis "Cannot get query results on queryPool 0x%" PRIx64 49509fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis " with index %d as data has not been collected for this index.", 49519fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis (uint64_t)(query_pool), first_query + i); 49525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 49535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 49545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 49559fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis return skip; 49569fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis} 49579fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis 49589fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlisstatic void PostCallRecordGetQueryPoolResults(layer_data *dev_data, VkQueryPool query_pool, uint32_t first_query, 49599fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis uint32_t query_count, 49609fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis unordered_map<QueryObject, vector<VkCommandBuffer>> *queries_in_flight) { 49619fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis for (uint32_t i = 0; i < query_count; ++i) { 49629fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis QueryObject query = {query_pool, first_query + i}; 49639fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis auto qif_pair = queries_in_flight->find(query); 49649fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis auto query_state_pair = dev_data->queryToStateMap.find(query); 49659fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis if (query_state_pair != dev_data->queryToStateMap.end()) { 49669fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis // Available and in flight 49679fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis if (qif_pair != queries_in_flight->end() && query_state_pair != dev_data->queryToStateMap.end() && 49689fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis query_state_pair->second) { 49699fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis for (auto cmd_buffer : qif_pair->second) { 49709a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb = GetCBNode(dev_data, cmd_buffer); 49719fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis auto query_event_pair = cb->waitedEventsBeforeQueryReset.find(query); 49729fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis if (query_event_pair != cb->waitedEventsBeforeQueryReset.end()) { 49739fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis for (auto event : query_event_pair->second) { 49749fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis dev_data->eventMap[event].needsSignaled = true; 49759fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis } 49769fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis } 49779fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis } 49789fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis } 49799fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis } 49809fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis } 49819fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis} 49829fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis 49839fdee42cd357379efb9aa27f90beb75d1f824955Tobin EhlisVKAPI_ATTR VkResult VKAPI_CALL GetQueryPoolResults(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, 49849fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis size_t dataSize, void *pData, VkDeviceSize stride, VkQueryResultFlags flags) { 498556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 49869fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis unordered_map<QueryObject, vector<VkCommandBuffer>> queries_in_flight; 49879fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 49889fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis bool skip = PreCallValidateGetQueryPoolResults(dev_data, queryPool, firstQuery, queryCount, flags, &queries_in_flight); 4989b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 4990cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 49919fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis VkResult result = 49929fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis dev_data->dispatch_table.GetQueryPoolResults(device, queryPool, firstQuery, queryCount, dataSize, pData, stride, flags); 49939fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis lock.lock(); 49949fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis PostCallRecordGetQueryPoolResults(dev_data, queryPool, firstQuery, queryCount, &queries_in_flight); 49959fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis lock.unlock(); 49969fdee42cd357379efb9aa27f90beb75d1f824955Tobin Ehlis return result; 49975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 49985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 4999825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Return true if given ranges intersect, else false 5000825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Prereq : For both ranges, range->end - range->start > 0. This case should have already resulted 5001825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// in an error so not checking that here 5002825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// pad_ranges bool indicates a linear and non-linear comparison which requires padding 50033251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski// In the case where padding is required, if an alias is encountered then a validation error is reported and skip 50043251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski// may be set by the callback function so caller should merge in skip value if padding case is possible. 50052ea938737c34152a86f5e453eaef7f77b45c0ea3Cort Stratton// This check can be skipped by passing skip_checks=true, for call sites outside the validation path. 50063251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinskistatic bool rangesIntersect(layer_data const *dev_data, MEMORY_RANGE const *range1, MEMORY_RANGE const *range2, bool *skip, 50072ea938737c34152a86f5e453eaef7f77b45c0ea3Cort Stratton bool skip_checks) { 50083251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski *skip = false; 5009825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis auto r1_start = range1->start; 5010825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis auto r1_end = range1->end; 5011825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis auto r2_start = range2->start; 5012825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis auto r2_end = range2->end; 5013825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis VkDeviceSize pad_align = 1; 5014825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis if (range1->linear != range2->linear) { 5015825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis pad_align = dev_data->phys_dev_properties.properties.limits.bufferImageGranularity; 5016825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis } 5017cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if ((r1_end & ~(pad_align - 1)) < (r2_start & ~(pad_align - 1))) return false; 5018cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if ((r1_start & ~(pad_align - 1)) > (r2_end & ~(pad_align - 1))) return false; 501947aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski 50202ea938737c34152a86f5e453eaef7f77b45c0ea3Cort Stratton if (!skip_checks && (range1->linear != range2->linear)) { 502153ecec26e80e4d18b57d24ed6eb91a3c9da4b95cTobin Ehlis // In linear vs. non-linear case, warn of aliasing 5022825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis const char *r1_linear_str = range1->linear ? "Linear" : "Non-linear"; 5023825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis const char *r1_type_str = range1->image ? "image" : "buffer"; 5024825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis const char *r2_linear_str = range2->linear ? "linear" : "non-linear"; 5025825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis const char *r2_type_str = range2->image ? "image" : "buffer"; 5026825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis auto obj_type = range1->image ? VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT : VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT; 50273251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski *skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, obj_type, range1->handle, 0, 50283251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski MEMTRACK_INVALID_ALIASING, "MEM", "%s %s 0x%" PRIx64 " is aliased with %s %s 0x%" PRIx64 50293251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski " which may indicate a bug. For further info refer to the " 50303251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Buffer-Image Granularity section of the Vulkan specification. " 50313251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "(https://www.khronos.org/registry/vulkan/specs/1.0-extensions/" 50323251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "xhtml/vkspec.html#resources-bufferimagegranularity)", 50333251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski r1_linear_str, r1_type_str, range1->handle, r2_linear_str, r2_type_str, range2->handle); 503447aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski } 5035825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis // Ranges intersect 5036825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis return true; 503747aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski} 5038623548a271287ae55415e45e3c654ee66d4e79ffTobin Ehlis// Simplified rangesIntersect that calls above function to check range1 for intersection with offset & end addresses 5039c3340a06ecac4d7b9540592cae339f8fc224d0b1Mark Lobodzinskibool rangesIntersect(layer_data const *dev_data, MEMORY_RANGE const *range1, VkDeviceSize offset, VkDeviceSize end) { 5040825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis // Create a local MEMORY_RANGE struct to wrap offset/size 5041825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis MEMORY_RANGE range_wrap; 5042825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis // Synch linear with range1 to avoid padding and potential validation error case 5043825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis range_wrap.linear = range1->linear; 5044825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis range_wrap.start = offset; 5045cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis range_wrap.end = end; 5046825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis bool tmp_bool; 50472ea938737c34152a86f5e453eaef7f77b45c0ea3Cort Stratton return rangesIntersect(dev_data, range1, &range_wrap, &tmp_bool, true); 5048825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis} 5049cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis// For given mem_info, set all ranges valid that intersect [offset-end] range 5050cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis// TODO : For ranges where there is no alias, we may want to create new buffer ranges that are valid 5051cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlisstatic void SetMemRangesValid(layer_data const *dev_data, DEVICE_MEM_INFO *mem_info, VkDeviceSize offset, VkDeviceSize end) { 5052cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis bool tmp_bool = false; 5053f6e16b28b808a342cb92768001afa2cfeee08a11Tobin Ehlis MEMORY_RANGE map_range = {}; 5054cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis map_range.linear = true; 5055cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis map_range.start = offset; 5056cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis map_range.end = end; 5057cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis for (auto &handle_range_pair : mem_info->bound_ranges) { 50582ea938737c34152a86f5e453eaef7f77b45c0ea3Cort Stratton if (rangesIntersect(dev_data, &handle_range_pair.second, &map_range, &tmp_bool, false)) { 5059cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis // TODO : WARN here if tmp_bool true? 5060cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis handle_range_pair.second.valid = true; 5061cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis } 5062cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis } 5063cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis} 50640ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton 50650ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Strattonstatic bool ValidateInsertMemoryRange(layer_data const *dev_data, uint64_t handle, DEVICE_MEM_INFO *mem_info, 50660ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton VkDeviceSize memoryOffset, VkMemoryRequirements memRequirements, bool is_image, 50670ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton bool is_linear, const char *api_name) { 50680ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton bool skip = false; 50690ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton 50700ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton MEMORY_RANGE range; 50710ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton range.image = is_image; 50720ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton range.handle = handle; 50730ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton range.linear = is_linear; 50740ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton range.valid = mem_info->global_valid; 50750ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton range.memory = mem_info->mem; 50760ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton range.start = memoryOffset; 50770ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton range.size = memRequirements.size; 50780ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton range.end = memoryOffset + memRequirements.size - 1; 50790ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton range.aliases.clear(); 50800ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton 50810ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton // Check for aliasing problems. 50820ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton for (auto &obj_range_pair : mem_info->bound_ranges) { 50830ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton auto check_range = &obj_range_pair.second; 50840ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton bool intersection_error = false; 50852ea938737c34152a86f5e453eaef7f77b45c0ea3Cort Stratton if (rangesIntersect(dev_data, &range, check_range, &intersection_error, false)) { 50860ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton skip |= intersection_error; 50870ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton range.aliases.insert(check_range); 50880ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton } 50890ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton } 50900ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton 50910ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton if (memoryOffset >= mem_info->alloc_info.allocationSize) { 50920ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton UNIQUE_VALIDATION_ERROR_CODE error_code = is_image ? VALIDATION_ERROR_00805 : VALIDATION_ERROR_00793; 50930ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton skip = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 50940ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton reinterpret_cast<uint64_t &>(mem_info->mem), __LINE__, error_code, "MEM", 50950ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton "In %s, attempting to bind memory (0x%" PRIxLEAST64 ") to object (0x%" PRIxLEAST64 50960ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton "), memoryOffset=0x%" PRIxLEAST64 " must be less than the memory allocation size 0x%" PRIxLEAST64 ". %s", 50970ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton api_name, reinterpret_cast<uint64_t &>(mem_info->mem), handle, memoryOffset, 50980ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton mem_info->alloc_info.allocationSize, validation_error_map[error_code]); 50990ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton } 51000ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton 51010ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton return skip; 51020ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton} 51030ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton 5104825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Object with given handle is being bound to memory w/ given mem_info struct. 5105825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Track the newly bound memory range with given memoryOffset 5106825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Also scan any previous ranges, track aliased ranges with new range, and flag an error if a linear 5107825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// and non-linear range incorrectly overlap. 5108825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Return true if an error is flagged and the user callback returns "true", otherwise false 5109825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// is_image indicates an image object, otherwise handle is for a buffer 5110825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// is_linear indicates a buffer or linear image 51110ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Strattonstatic void InsertMemoryRange(layer_data const *dev_data, uint64_t handle, DEVICE_MEM_INFO *mem_info, VkDeviceSize memoryOffset, 51120ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton VkMemoryRequirements memRequirements, bool is_image, bool is_linear) { 51135360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis MEMORY_RANGE range; 5114825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis 5115825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis range.image = is_image; 511647aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski range.handle = handle; 5117825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis range.linear = is_linear; 5118f541bf53dee6daf82a4c8304354eac599a884d29Tobin Ehlis range.valid = mem_info->global_valid; 5119825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis range.memory = mem_info->mem; 512047aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski range.start = memoryOffset; 5121825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis range.size = memRequirements.size; 512247aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski range.end = memoryOffset + memRequirements.size - 1; 51235360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis range.aliases.clear(); 51245360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis // Update Memory aliasing 512575f4c8cec0996021a4258b9bf920a9e0fea4eac1Tobin 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 51265360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis // inserted into map before loop to get the final ptr, then we may enter loop when not needed & we check range against itself 51275360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis std::unordered_set<MEMORY_RANGE *> tmp_alias_ranges; 5128825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis for (auto &obj_range_pair : mem_info->bound_ranges) { 5129825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis auto check_range = &obj_range_pair.second; 51305360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis bool intersection_error = false; 51312ea938737c34152a86f5e453eaef7f77b45c0ea3Cort Stratton if (rangesIntersect(dev_data, &range, check_range, &intersection_error, true)) { 5132825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis range.aliases.insert(check_range); 51335360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis tmp_alias_ranges.insert(check_range); 5134825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis } 5135825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis } 51365360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis mem_info->bound_ranges[handle] = std::move(range); 51375360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis for (auto tmp_range : tmp_alias_ranges) { 51385360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis tmp_range->aliases.insert(&mem_info->bound_ranges[handle]); 51395360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis } 5140825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis if (is_image) 5141825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis mem_info->bound_images.insert(handle); 5142825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis else 5143825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis mem_info->bound_buffers.insert(handle); 514447aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski} 514547aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski 51460ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Strattonstatic bool ValidateInsertImageMemoryRange(layer_data const *dev_data, VkImage image, DEVICE_MEM_INFO *mem_info, 51470ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton VkDeviceSize mem_offset, VkMemoryRequirements mem_reqs, bool is_linear, 51480ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton const char *api_name) { 51490ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton return ValidateInsertMemoryRange(dev_data, reinterpret_cast<uint64_t &>(image), mem_info, mem_offset, mem_reqs, true, is_linear, 51500ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton api_name); 51510ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton} 51520ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Strattonstatic void InsertImageMemoryRange(layer_data const *dev_data, VkImage image, DEVICE_MEM_INFO *mem_info, VkDeviceSize mem_offset, 51530ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton VkMemoryRequirements mem_reqs, bool is_linear) { 51540ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton InsertMemoryRange(dev_data, reinterpret_cast<uint64_t &>(image), mem_info, mem_offset, mem_reqs, true, is_linear); 5155825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis} 5156825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis 51570ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Strattonstatic bool ValidateInsertBufferMemoryRange(layer_data const *dev_data, VkBuffer buffer, DEVICE_MEM_INFO *mem_info, 51580ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton VkDeviceSize mem_offset, VkMemoryRequirements mem_reqs, const char *api_name) { 51590ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton return ValidateInsertMemoryRange(dev_data, reinterpret_cast<uint64_t &>(buffer), mem_info, mem_offset, mem_reqs, false, true, 51600ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton api_name); 51610ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton} 51620ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Strattonstatic void InsertBufferMemoryRange(layer_data const *dev_data, VkBuffer buffer, DEVICE_MEM_INFO *mem_info, VkDeviceSize mem_offset, 51630ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton VkMemoryRequirements mem_reqs) { 51640ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton InsertMemoryRange(dev_data, reinterpret_cast<uint64_t &>(buffer), mem_info, mem_offset, mem_reqs, false, true); 5165825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis} 5166825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis 5167825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// Remove MEMORY_RANGE struct for give handle from bound_ranges of mem_info 5168825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// is_image indicates if handle is for image or buffer 5169825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// This function will also remove the handle-to-index mapping from the appropriate 5170825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis// map and clean up any aliases for range being removed. 5171825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlisstatic void RemoveMemoryRange(uint64_t handle, DEVICE_MEM_INFO *mem_info, bool is_image) { 5172825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis auto erase_range = &mem_info->bound_ranges[handle]; 5173825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis for (auto alias_range : erase_range->aliases) { 5174825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis alias_range->aliases.erase(erase_range); 517547aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski } 51765360871dd546e8aa7c1a273e9036c201fe4e3ffbTobin Ehlis erase_range->aliases.clear(); 5177825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis mem_info->bound_ranges.erase(handle); 51781cba4e1b5940c6818572e05dcad5a3a47fafbc9eTobin Ehlis if (is_image) { 5179825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis mem_info->bound_images.erase(handle); 51801cba4e1b5940c6818572e05dcad5a3a47fafbc9eTobin Ehlis } else { 5181825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis mem_info->bound_buffers.erase(handle); 51821cba4e1b5940c6818572e05dcad5a3a47fafbc9eTobin Ehlis } 518347aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski} 518447aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski 5185842b2d28ded1c6e2c38491a81213d0e1d1b7295aMark Lobodzinskivoid RemoveBufferMemoryRange(uint64_t handle, DEVICE_MEM_INFO *mem_info) { RemoveMemoryRange(handle, mem_info, false); } 5186825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis 51878c59133586421be878d393799b30044497f77727Mark Lobodzinskivoid RemoveImageMemoryRange(uint64_t handle, DEVICE_MEM_INFO *mem_info) { RemoveMemoryRange(handle, mem_info, true); } 5188825446075d5f6c6b531754c0709bddd9dae8945fTobin Ehlis 5189bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyBuffer(VkDevice device, VkBuffer buffer, const VkAllocationCallbacks *pAllocator) { 519056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 5191e1056daefb39e3a3fed0088874725c56a1359e54Tobin Ehlis BUFFER_STATE *buffer_state = nullptr; 5192e1056daefb39e3a3fed0088874725c56a1359e54Tobin Ehlis VK_OBJECT obj_struct; 5193b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 5194e1056daefb39e3a3fed0088874725c56a1359e54Tobin Ehlis bool skip = PreCallValidateDestroyBuffer(dev_data, buffer, &buffer_state, &obj_struct); 5195e1056daefb39e3a3fed0088874725c56a1359e54Tobin Ehlis if (!skip) { 5196b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 51974a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyBuffer(device, buffer, pAllocator); 5198e1056daefb39e3a3fed0088874725c56a1359e54Tobin Ehlis lock.lock(); 5199405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (buffer != VK_NULL_HANDLE) { 5200405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyBuffer(dev_data, buffer, buffer_state, obj_struct); 5201405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 520247aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski } 52035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 52045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5205bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyBufferView(VkDevice device, VkBufferView bufferView, const VkAllocationCallbacks *pAllocator) { 520656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 5207f61017735c3291a2665487f2bac310578fc60a68Tobin Ehlis // Common data objects used pre & post call 52088e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis BUFFER_VIEW_STATE *buffer_view_state = nullptr; 52098e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis VK_OBJECT obj_struct; 5210a123662876eebfa844faa65ae3f071d3d77618ebTobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 52118e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis // Validate state before calling down chain, update common data if we'll be calling down chain 52128e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis bool skip = PreCallValidateDestroyBufferView(dev_data, bufferView, &buffer_view_state, &obj_struct); 521338e26abbaa884eb48bfec4ddb4e0ae2c90634e06Tobin Ehlis if (!skip) { 521438e26abbaa884eb48bfec4ddb4e0ae2c90634e06Tobin Ehlis lock.unlock(); 52154a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyBufferView(device, bufferView, pAllocator); 52168e0ffae5b5c87fa062229b8c003be10c7e48aea1Tobin Ehlis lock.lock(); 5217405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (bufferView != VK_NULL_HANDLE) { 5218405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyBufferView(dev_data, bufferView, buffer_view_state, obj_struct); 5219405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 52205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 52215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 52225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 52232a0dd15a44bf665c97a3ff6adcbe7fe5853cdf60Tobin EhlisVKAPI_ATTR void VKAPI_CALL DestroyImage(VkDevice device, VkImage image, const VkAllocationCallbacks *pAllocator) { 522456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 52251facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis IMAGE_STATE *image_state = nullptr; 52262a0dd15a44bf665c97a3ff6adcbe7fe5853cdf60Tobin Ehlis VK_OBJECT obj_struct; 52272a0dd15a44bf665c97a3ff6adcbe7fe5853cdf60Tobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 52282a0dd15a44bf665c97a3ff6adcbe7fe5853cdf60Tobin Ehlis bool skip = PreCallValidateDestroyImage(dev_data, image, &image_state, &obj_struct); 52292a0dd15a44bf665c97a3ff6adcbe7fe5853cdf60Tobin Ehlis if (!skip) { 5230f940225c9e5e3e14b3f5a32d3ea360b585614600Tobin Ehlis lock.unlock(); 52314a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyImage(device, image, pAllocator); 52322a0dd15a44bf665c97a3ff6adcbe7fe5853cdf60Tobin Ehlis lock.lock(); 5233405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (image != VK_NULL_HANDLE) { 5234405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyImage(dev_data, image, image_state, obj_struct); 5235405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 52365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 52375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 52385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 52394261f1e2c91c90ce040ab36a13c9d92f6e988f10Mark Lobodzinskistatic bool ValidateMemoryTypes(const layer_data *dev_data, const DEVICE_MEM_INFO *mem_info, const uint32_t memory_type_bits, 5240f634be57d858a71969b3183cd0e322fe1d0ad0fbMike Weiblen const char *funcName, UNIQUE_VALIDATION_ERROR_CODE msgCode) { 52413251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 5242de1d2592cdd497642de5b0e6f27ebc439018383bTobin Ehlis if (((1 << mem_info->alloc_info.memoryTypeIndex) & memory_type_bits) == 0) { 52433251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 52443251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<const uint64_t &>(mem_info->mem), __LINE__, msgCode, "MT", 52453251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "%s(): MemoryRequirements->memoryTypeBits (0x%X) for this object type are not compatible with the memory " 52463251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "type (0x%X) of this memory object 0x%" PRIx64 ". %s", 52473251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski funcName, memory_type_bits, mem_info->alloc_info.memoryTypeIndex, 52483251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<const uint64_t &>(mem_info->mem), validation_error_map[msgCode]); 52494261f1e2c91c90ce040ab36a13c9d92f6e988f10Mark Lobodzinski } 52503251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 52514261f1e2c91c90ce040ab36a13c9d92f6e988f10Mark Lobodzinski} 52524261f1e2c91c90ce040ab36a13c9d92f6e988f10Mark Lobodzinski 5253160335c453ec51cc48bdef78e8befdb3c86ff292Cort Strattonstatic bool PreCallValidateBindBufferMemory(layer_data *dev_data, VkBuffer buffer, BUFFER_STATE *buffer_state, VkDeviceMemory mem, 5254160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton VkDeviceSize memoryOffset) { 52559207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton bool skip = false; 52565cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis if (buffer_state) { 5257160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton std::unique_lock<std::mutex> lock(global_lock); 52589207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton // Track objects tied to memory 52599207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton uint64_t buffer_handle = reinterpret_cast<uint64_t &>(buffer); 52607a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski skip = ValidateSetMemBinding(dev_data, mem, buffer_handle, kVulkanObjectTypeBuffer, "vkBindBufferMemory()"); 52612eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis if (!buffer_state->memory_requirements_checked) { 52622eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis // There's not an explicit requirement in the spec to call vkGetBufferMemoryRequirements() prior to calling 52639207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton // BindBufferMemory, but it's implied in that memory being bound must conform with VkMemoryRequirements from 52649207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton // vkGetBufferMemoryRequirements() 52659207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, 52669207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton buffer_handle, __LINE__, DRAWSTATE_INVALID_BUFFER, "DS", 52679207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton "vkBindBufferMemory(): Binding memory to buffer 0x%" PRIxLEAST64 52689207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton " but vkGetBufferMemoryRequirements() has not been called on that buffer.", 52699207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton buffer_handle); 52702eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis // Make the call for them so we can verify the state 52712eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis lock.unlock(); 52729207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton dev_data->dispatch_table.GetBufferMemoryRequirements(dev_data->device, buffer, &buffer_state->requirements); 52732eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis lock.lock(); 52742eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis } 527547aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski 52760ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton // Validate bound memory range information 52779a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto mem_info = GetMemObjInfo(dev_data, mem); 527857fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis if (mem_info) { 52790ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton skip |= ValidateInsertBufferMemoryRange(dev_data, buffer, mem_info, memoryOffset, buffer_state->requirements, 52800ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton "vkBindBufferMemory()"); 52819207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton skip |= ValidateMemoryTypes(dev_data, mem_info, buffer_state->requirements.memoryTypeBits, "vkBindBufferMemory()", 52829207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton VALIDATION_ERROR_00797); 528347aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski } 528447aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski 52852c905c8b5aca814df6c680348145ca48885f9f69Dustin Graves // Validate memory requirements alignment 528616769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton if (SafeModulo(memoryOffset, buffer_state->requirements.alignment) != 0) { 5287f60e41965223825191505eebc96491bb52e494a2Cort Stratton skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, 5288f60e41965223825191505eebc96491bb52e494a2Cort Stratton buffer_handle, __LINE__, VALIDATION_ERROR_02174, "DS", 52899207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton "vkBindBufferMemory(): memoryOffset is 0x%" PRIxLEAST64 52909207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton " but must be an integer multiple of the " 52919207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton "VkMemoryRequirements::alignment value 0x%" PRIxLEAST64 52929207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton ", returned from a call to vkGetBufferMemoryRequirements with buffer. %s", 52939207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton memoryOffset, buffer_state->requirements.alignment, validation_error_map[VALIDATION_ERROR_02174]); 52942c905c8b5aca814df6c680348145ca48885f9f69Dustin Graves } 5295ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller 5296160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton // Validate memory requirements size 5297160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton if (buffer_state->requirements.size > (mem_info->alloc_info.allocationSize - memoryOffset)) { 5298160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, 5299160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton buffer_handle, __LINE__, VALIDATION_ERROR_02175, "DS", 5300160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton "vkBindBufferMemory(): memory size minus memoryOffset is 0x%" PRIxLEAST64 5301160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton " but must be at least as large as " 5302160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton "VkMemoryRequirements::size value 0x%" PRIxLEAST64 5303160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton ", returned from a call to vkGetBufferMemoryRequirements with buffer. %s", 5304160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton mem_info->alloc_info.allocationSize - memoryOffset, buffer_state->requirements.size, 5305160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton validation_error_map[VALIDATION_ERROR_02175]); 5306160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton } 5307160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton 53082c905c8b5aca814df6c680348145ca48885f9f69Dustin Graves // Validate device limits alignments 5309ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller static const VkBufferUsageFlagBits usage_list[3] = { 5310ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller static_cast<VkBufferUsageFlagBits>(VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT), 5311bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT}; 5312bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski static const char *memory_type[3] = {"texel", "uniform", "storage"}; 5313bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski static const char *offset_name[3] = {"minTexelBufferOffsetAlignment", "minUniformBufferOffsetAlignment", 5314bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "minStorageBufferOffsetAlignment"}; 5315cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski 53169207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton // TODO: vk_validation_stats.py cannot abide braces immediately preceding or following a validation error enum 5317cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // clang-format off 53180ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton static const UNIQUE_VALIDATION_ERROR_CODE msgCode[3] = { VALIDATION_ERROR_00794, VALIDATION_ERROR_00795, 53190ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton VALIDATION_ERROR_00796 }; 5320cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // clang-format on 5321ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller 5322ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller // Keep this one fresh! 5323ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller const VkDeviceSize offset_requirement[3] = { 5324ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller dev_data->phys_dev_properties.properties.limits.minTexelBufferOffsetAlignment, 5325ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller dev_data->phys_dev_properties.properties.limits.minUniformBufferOffsetAlignment, 5326bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski dev_data->phys_dev_properties.properties.limits.minStorageBufferOffsetAlignment}; 53278718070cf3e206488c168f1e6b9dd06d6880c9bcTobin Ehlis VkBufferUsageFlags usage = dev_data->bufferMap[buffer].get()->createInfo.usage; 5328ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller 5329ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller for (int i = 0; i < 3; i++) { 5330ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller if (usage & usage_list[i]) { 533116769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton if (SafeModulo(memoryOffset, offset_requirement[i]) != 0) { 53329207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton skip |= log_msg( 5333f60e41965223825191505eebc96491bb52e494a2Cort Stratton dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, buffer_handle, 5334cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski __LINE__, msgCode[i], "DS", "vkBindBufferMemory(): %s memoryOffset is 0x%" PRIxLEAST64 5335cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " but must be a multiple of " 5336cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "device limit %s 0x%" PRIxLEAST64 ". %s", 5337cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski memory_type[i], memoryOffset, offset_name[i], offset_requirement[i], validation_error_map[msgCode[i]]); 5338ba4316045bf5f1054629bb7c2fced7bae98ed52aMark Mueller } 53392c905c8b5aca814df6c680348145ca48885f9f69Dustin Graves } 53402c905c8b5aca814df6c680348145ca48885f9f69Dustin Graves } 53415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 53429207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton return skip; 53439207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton} 53449207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton 5345160335c453ec51cc48bdef78e8befdb3c86ff292Cort Strattonstatic void PostCallRecordBindBufferMemory(layer_data *dev_data, VkBuffer buffer, BUFFER_STATE *buffer_state, VkDeviceMemory mem, 5346160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton VkDeviceSize memoryOffset) { 53479207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton if (buffer_state) { 5348160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton std::unique_lock<std::mutex> lock(global_lock); 53490ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton // Track bound memory range information 53500ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton auto mem_info = GetMemObjInfo(dev_data, mem); 53510ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton if (mem_info) { 53520ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton InsertBufferMemoryRange(dev_data, buffer, mem_info, memoryOffset, buffer_state->requirements); 53530ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton } 53540ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton 5355c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton // Track objects tied to memory 5356c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton uint64_t buffer_handle = reinterpret_cast<uint64_t &>(buffer); 53577a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski SetMemBinding(dev_data, mem, buffer_handle, kVulkanObjectTypeBuffer, "vkBindBufferMemory()"); 5358c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton 53599207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton buffer_state->binding.mem = mem; 53609207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton buffer_state->binding.offset = memoryOffset; 53619207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton buffer_state->binding.size = buffer_state->requirements.size; 53629207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton } 53639207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton} 53649207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton 53659207132ef623d47fcbdfeb9ebc796eade35a2f4cCort StrattonVKAPI_ATTR VkResult VKAPI_CALL BindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory mem, VkDeviceSize memoryOffset) { 53669207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 53679207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 5368160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton auto buffer_state = GetBufferState(dev_data, buffer); 5369160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton bool skip = PreCallValidateBindBufferMemory(dev_data, buffer, buffer_state, mem, memoryOffset); 53709207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton if (!skip) { 53714a0754042cf090e131e9e769d8a3633c228625beChris Forbes result = dev_data->dispatch_table.BindBufferMemory(device, buffer, mem, memoryOffset); 53729207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton if (result == VK_SUCCESS) { 5373160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton PostCallRecordBindBufferMemory(dev_data, buffer, buffer_state, mem, memoryOffset); 53749207132ef623d47fcbdfeb9ebc796eade35a2f4cCort Stratton } 53755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 53765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 53775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 53785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5379bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL GetBufferMemoryRequirements(VkDevice device, VkBuffer buffer, 5380bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkMemoryRequirements *pMemoryRequirements) { 538156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 538215caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis dev_data->dispatch_table.GetBufferMemoryRequirements(device, buffer, pMemoryRequirements); 53839a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto buffer_state = GetBufferState(dev_data, buffer); 538415caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis if (buffer_state) { 538515caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis buffer_state->requirements = *pMemoryRequirements; 53862eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis buffer_state->memory_requirements_checked = true; 538715caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis } 53885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 53895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5390bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL GetImageMemoryRequirements(VkDevice device, VkImage image, VkMemoryRequirements *pMemoryRequirements) { 539156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 539215caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis dev_data->dispatch_table.GetImageMemoryRequirements(device, image, pMemoryRequirements); 53939a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_state = GetImageState(dev_data, image); 539415caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis if (image_state) { 539515caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis image_state->requirements = *pMemoryRequirements; 53962eda842d84a02b9d5bfb03d6c26c5f7c00e6e8beTobin Ehlis image_state->memory_requirements_checked = true; 539715caa3e8f88f57bdcc42a3eabb9375e57007e5aaTobin Ehlis } 53985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 5399593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 5400bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyImageView(VkDevice device, VkImageView imageView, const VkAllocationCallbacks *pAllocator) { 540156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 5402f61017735c3291a2665487f2bac310578fc60a68Tobin Ehlis // Common data objects used pre & post call 5403f61017735c3291a2665487f2bac310578fc60a68Tobin Ehlis IMAGE_VIEW_STATE *image_view_state = nullptr; 5404f61017735c3291a2665487f2bac310578fc60a68Tobin Ehlis VK_OBJECT obj_struct; 5405a123662876eebfa844faa65ae3f071d3d77618ebTobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 5406f61017735c3291a2665487f2bac310578fc60a68Tobin Ehlis bool skip = PreCallValidateDestroyImageView(dev_data, imageView, &image_view_state, &obj_struct); 5407d85c42a6c1d6ad7a6f684c5bd793aab482b7705cTobin Ehlis if (!skip) { 5408d85c42a6c1d6ad7a6f684c5bd793aab482b7705cTobin Ehlis lock.unlock(); 54094a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyImageView(device, imageView, pAllocator); 5410f61017735c3291a2665487f2bac310578fc60a68Tobin Ehlis lock.lock(); 5411405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (imageView != VK_NULL_HANDLE) { 5412405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyImageView(dev_data, imageView, image_view_state, obj_struct); 5413405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 5414d85c42a6c1d6ad7a6f684c5bd793aab482b7705cTobin Ehlis } 54155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 54165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5417bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyShaderModule(VkDevice device, VkShaderModule shaderModule, 5418bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator) { 541956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 5420918c283ac4f8c604b79abd0c8b5706d2a7352a34Chris Forbes 5421b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 542251ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->shaderModuleMap.erase(shaderModule); 5423b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 5424918c283ac4f8c604b79abd0c8b5706d2a7352a34Chris Forbes 542551ea774638f432bd8e700ec8291a980f405f429eTobin Ehlis dev_data->dispatch_table.DestroyShaderModule(device, shaderModule, pAllocator); 54265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 54275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 54284c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlisstatic bool PreCallValidateDestroyPipeline(layer_data *dev_data, VkPipeline pipeline, PIPELINE_STATE **pipeline_state, 54298bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis VK_OBJECT *obj_struct) { 543094165f5005d1fa37801d49067fe7751789b89d27Tobin Ehlis *pipeline_state = getPipelineState(dev_data, pipeline); 54317a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski *obj_struct = {reinterpret_cast<uint64_t &>(pipeline), kVulkanObjectTypePipeline}; 5432cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_pipeline) return false; 54338bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis bool skip = false; 54348bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis if (*pipeline_state) { 54351803032f91d772ff3589c9f5a51ade5b299ba538Tobin Ehlis skip |= ValidateObjectNotInUse(dev_data, *pipeline_state, *obj_struct, VALIDATION_ERROR_00555); 54368bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis } 54378bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis return skip; 54388bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis} 54398bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis 54404c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlisstatic void PostCallRecordDestroyPipeline(layer_data *dev_data, VkPipeline pipeline, PIPELINE_STATE *pipeline_state, 54418bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis VK_OBJECT obj_struct) { 54428bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis // Any bound cmd buffers are now invalid 544339c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis invalidateCommandBuffers(dev_data, pipeline_state->cb_bindings, obj_struct); 54448bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis dev_data->pipelineMap.erase(pipeline); 54458bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis} 54468bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis 5447bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyPipeline(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks *pAllocator) { 544856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 54494c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis PIPELINE_STATE *pipeline_state = nullptr; 54508bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis VK_OBJECT obj_struct; 5451e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 54528bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis bool skip = PreCallValidateDestroyPipeline(dev_data, pipeline, &pipeline_state, &obj_struct); 5453f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis if (!skip) { 5454f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis lock.unlock(); 54554a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyPipeline(device, pipeline, pAllocator); 54568bd2ec9a26cca477de2de93304774cdba0af77bcTobin Ehlis lock.lock(); 5457405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (pipeline != VK_NULL_HANDLE) { 5458405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyPipeline(dev_data, pipeline, pipeline_state, obj_struct); 5459405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 5460f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis } 54615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 54625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5463bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyPipelineLayout(VkDevice device, VkPipelineLayout pipelineLayout, 5464bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator) { 546556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 5466e28cddb35c63274c13873b9a7060ad43b255c6f1Tobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 54676792ea7cc0ce5fa64b7bd6c946460608cbda91c7Tobin Ehlis dev_data->pipelineLayoutMap.erase(pipelineLayout); 5468e28cddb35c63274c13873b9a7060ad43b255c6f1Tobin Ehlis lock.unlock(); 5469e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis 54704a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyPipelineLayout(device, pipelineLayout, pAllocator); 54715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 54725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5473d31a44af6da568692a73201825459689c9431867Tobin Ehlisstatic bool PreCallValidateDestroySampler(layer_data *dev_data, VkSampler sampler, SAMPLER_STATE **sampler_state, 5474806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis VK_OBJECT *obj_struct) { 54759a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *sampler_state = GetSamplerState(dev_data, sampler); 54767a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski *obj_struct = {reinterpret_cast<uint64_t &>(sampler), kVulkanObjectTypeSampler}; 5477cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_sampler) return false; 5478806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis bool skip = false; 5479806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis if (*sampler_state) { 5480806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis skip |= ValidateObjectNotInUse(dev_data, *sampler_state, *obj_struct, VALIDATION_ERROR_00837); 5481806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis } 5482806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis return skip; 5483806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis} 5484806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis 5485d31a44af6da568692a73201825459689c9431867Tobin Ehlisstatic void PostCallRecordDestroySampler(layer_data *dev_data, VkSampler sampler, SAMPLER_STATE *sampler_state, 5486806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis VK_OBJECT obj_struct) { 5487806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis // Any bound cmd buffers are now invalid 5488cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (sampler_state) invalidateCommandBuffers(dev_data, sampler_state->cb_bindings, obj_struct); 5489806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis dev_data->samplerMap.erase(sampler); 5490806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis} 5491806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis 5492bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroySampler(VkDevice device, VkSampler sampler, const VkAllocationCallbacks *pAllocator) { 549356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 5494d31a44af6da568692a73201825459689c9431867Tobin Ehlis SAMPLER_STATE *sampler_state = nullptr; 5495806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis VK_OBJECT obj_struct; 549656f8a8f9b7e8c01d76d73be117ebcb66035db6dfTobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 5497806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis bool skip = PreCallValidateDestroySampler(dev_data, sampler, &sampler_state, &obj_struct); 5498f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis if (!skip) { 5499f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis lock.unlock(); 55004a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroySampler(device, sampler, pAllocator); 5501806095ea973371ad4c82bd0c2c58d53cc5557f0bTobin Ehlis lock.lock(); 5502405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (sampler != VK_NULL_HANDLE) { 5503405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroySampler(dev_data, sampler, sampler_state, obj_struct); 5504405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 5505f57cf525e45f3a65e25c2691464d65e29a79ba77Tobin Ehlis } 55065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 55075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 550879c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlisstatic void PostCallRecordDestroyDescriptorSetLayout(layer_data *dev_data, VkDescriptorSetLayout ds_layout) { 550979c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlis dev_data->descriptorSetLayoutMap.erase(ds_layout); 551079c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlis} 551179c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlis 5512bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyDescriptorSetLayout(VkDevice device, VkDescriptorSetLayout descriptorSetLayout, 5513bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator) { 551456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 551579c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlis dev_data->dispatch_table.DestroyDescriptorSetLayout(device, descriptorSetLayout, pAllocator); 551679c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 551779c5b660cd51e93e279c1aa001a42801d3bf7a5dTobin Ehlis PostCallRecordDestroyDescriptorSetLayout(dev_data, descriptorSetLayout); 55185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 55195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5520c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlisstatic bool PreCallValidateDestroyDescriptorPool(layer_data *dev_data, VkDescriptorPool pool, 5521a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis DESCRIPTOR_POOL_STATE **desc_pool_state, VK_OBJECT *obj_struct) { 55229a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *desc_pool_state = GetDescriptorPoolState(dev_data, pool); 55237a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski *obj_struct = {reinterpret_cast<uint64_t &>(pool), kVulkanObjectTypeDescriptorPool}; 5524cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_descriptor_pool) return false; 5525c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis bool skip = false; 5526c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis if (*desc_pool_state) { 55271803032f91d772ff3589c9f5a51ade5b299ba538Tobin Ehlis skip |= ValidateObjectNotInUse(dev_data, *desc_pool_state, *obj_struct, VALIDATION_ERROR_00901); 5528c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis } 5529c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis return skip; 5530c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis} 5531c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis 5532c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlisstatic void PostCallRecordDestroyDescriptorPool(layer_data *dev_data, VkDescriptorPool descriptorPool, 5533a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis DESCRIPTOR_POOL_STATE *desc_pool_state, VK_OBJECT obj_struct) { 5534c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis // Any bound cmd buffers are now invalid 553539c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis invalidateCommandBuffers(dev_data, desc_pool_state->cb_bindings, obj_struct); 5536c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis // Free sets that were in this pool 5537c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis for (auto ds : desc_pool_state->sets) { 5538c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis freeDescriptorSet(dev_data, ds); 5539c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis } 5540c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis dev_data->descriptorPoolMap.erase(descriptorPool); 5541c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis} 5542c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis 5543bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, 5544bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator) { 554556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 5546a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis DESCRIPTOR_POOL_STATE *desc_pool_state = nullptr; 5547c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis VK_OBJECT obj_struct; 5548c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 5549c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis bool skip = PreCallValidateDestroyDescriptorPool(dev_data, descriptorPool, &desc_pool_state, &obj_struct); 5550c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis if (!skip) { 5551c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis lock.unlock(); 5552c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis dev_data->dispatch_table.DestroyDescriptorPool(device, descriptorPool, pAllocator); 5553c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis lock.lock(); 5554405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (descriptorPool != VK_NULL_HANDLE) { 5555405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyDescriptorPool(dev_data, descriptorPool, desc_pool_state, obj_struct); 5556405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 5557c656e38f76da254b8b19e653d0945cabb43329bcTobin Ehlis } 55585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 55593251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski// Verify cmdBuffer in given cb_node is not in global in-flight set, and return skip result 5560bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis// If this is a secondary command buffer, then make sure its primary is also in-flight 5561bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis// If primary is not in-flight, then remove secondary from global in-flight set 5562bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis// This function is only valid at a point when cmdBuffer is being reset or freed 5563cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlisstatic bool checkCommandBufferInFlight(layer_data *dev_data, const GLOBAL_CB_NODE *cb_node, const char *action, 5564cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlis UNIQUE_VALIDATION_ERROR_CODE error_code) { 55653251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 5566bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis if (dev_data->globalInFlightCmdBuffers.count(cb_node->commandBuffer)) { 5567bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis // Primary CB or secondary where primary is also in-flight is an error 5568bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis if ((cb_node->createInfo.level != VK_COMMAND_BUFFER_LEVEL_SECONDARY) || 5569bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis (dev_data->globalInFlightCmdBuffers.count(cb_node->primaryCommandBuffer))) { 55703251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 55713251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<const uint64_t &>(cb_node->commandBuffer), __LINE__, error_code, "DS", 55723251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Attempt to %s command buffer (0x%p) which is in use. %s", action, cb_node->commandBuffer, 55733251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski validation_error_map[error_code]); 5574bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis } 5575bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis } 55763251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 5577bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis} 5578a964cad279f9749cd9ebfc7555247ff3bff26d53Chris Forbes 5579bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis// Iterate over all cmdBuffers in given commandPool and verify that each is not in use 5580cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlisstatic bool checkCommandBuffersInFlight(layer_data *dev_data, COMMAND_POOL_NODE *pPool, const char *action, 5581cdc73d5b6b64942b377db7220cd16b4045f73c9aTobin Ehlis UNIQUE_VALIDATION_ERROR_CODE error_code) { 55823251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 5583a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes for (auto cmd_buffer : pPool->commandBuffers) { 5584a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes if (dev_data->globalInFlightCmdBuffers.count(cmd_buffer)) { 55853251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= checkCommandBufferInFlight(dev_data, GetCBNode(dev_data, cmd_buffer), action, error_code); 5586bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis } 5587bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis } 55883251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 5589bc300ace5ad8d1935d42ee5dbbf36ce6ace4c0e8Tobin Ehlis} 55905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5591a01b5eb150981aad061238e64b173d0da8c11140Chris Forbesstatic void clearCommandBuffersInFlight(layer_data *dev_data, COMMAND_POOL_NODE *pPool) { 5592a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes for (auto cmd_buffer : pPool->commandBuffers) { 5593a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes dev_data->globalInFlightCmdBuffers.erase(cmd_buffer); 5594a964cad279f9749cd9ebfc7555247ff3bff26d53Chris Forbes } 5595a964cad279f9749cd9ebfc7555247ff3bff26d53Chris Forbes} 5596a964cad279f9749cd9ebfc7555247ff3bff26d53Chris Forbes 5597bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL FreeCommandBuffers(VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount, 5598bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkCommandBuffer *pCommandBuffers) { 559956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 56003251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 5601b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 5602c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes 56035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < commandBufferCount; i++) { 56049a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, pCommandBuffers[i]); 56055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Delete CB information structure, and remove from commandBufferMap 56069f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis if (cb_node) { 56073251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= checkCommandBufferInFlight(dev_data, cb_node, "free", VALIDATION_ERROR_00096); 5608c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes } 5609c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes } 5610c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes 56113251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (skip) return; 5612c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes 56139a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pPool = GetCommandPoolNode(dev_data, commandPool); 5614c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes for (uint32_t i = 0; i < commandBufferCount; i++) { 56159a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, pCommandBuffers[i]); 5616c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes // Delete CB information structure, and remove from commandBufferMap 56179f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis if (cb_node) { 56189f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis dev_data->globalInFlightCmdBuffers.erase(cb_node->commandBuffer); 56195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // reset prior to delete for data clean-up 56209f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis resetCB(dev_data, cb_node->commandBuffer); 56219f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis dev_data->commandBufferMap.erase(cb_node->commandBuffer); 56229f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis delete cb_node; 56235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 56245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 56255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Remove commandBuffer reference from commandPoolMap 5626c05d773a018aa47e89841533a6968d9e5b314038Chris Forbes pPool->commandBuffers.remove(pCommandBuffers[i]); 56275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5628b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 5629e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis 56304a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.FreeCommandBuffers(device, commandPool, commandBufferCount, pCommandBuffers); 56315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 56325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 563389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateCommandPool(VkDevice device, const VkCommandPoolCreateInfo *pCreateInfo, 5634bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkCommandPool *pCommandPool) { 563556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 56365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 56374a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateCommandPool(device, pCreateInfo, pAllocator, pCommandPool); 56385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 56395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 5640b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 56415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->commandPoolMap[*pCommandPool].createFlags = pCreateInfo->flags; 56425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->commandPoolMap[*pCommandPool].queueFamilyIndex = pCreateInfo->queueFamilyIndex; 56435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 56445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 56455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 56465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 564789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateQueryPool(VkDevice device, const VkQueryPoolCreateInfo *pCreateInfo, 564889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkQueryPool *pQueryPool) { 564956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 56500c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis bool skip = false; 56510c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis if (pCreateInfo && pCreateInfo->queryType == VK_QUERY_TYPE_PIPELINE_STATISTICS) { 56520c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis if (!dev_data->enabled_features.pipelineStatisticsQuery) { 56530c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT, 0, 56540c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis __LINE__, VALIDATION_ERROR_01006, "DS", 56550c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis "Query pool with type VK_QUERY_TYPE_PIPELINE_STATISTICS created on a device " 56560c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis "with VkDeviceCreateInfo.pEnabledFeatures.pipelineStatisticsQuery == VK_FALSE. %s", 56570c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis validation_error_map[VALIDATION_ERROR_01006]); 56580c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis } 56590c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis } 56600c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis 56610c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 56620c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis if (!skip) { 56630c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis result = dev_data->dispatch_table.CreateQueryPool(device, pCreateInfo, pAllocator, pQueryPool); 56640c45ab93ccfb9d39698ae47d6102d2e308ff476eTobin Ehlis } 56655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (result == VK_SUCCESS) { 5666b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 5667eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis QUERY_POOL_NODE *qp_node = &dev_data->queryPoolMap[*pQueryPool]; 5668eafbf0b68ee6ea6e0bf33f07e0058d00a96efd9aTobin Ehlis qp_node->createInfo = *pCreateInfo; 56695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 56705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 56715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 56725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 56735f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlisstatic bool PreCallValidateDestroyCommandPool(layer_data *dev_data, VkCommandPool pool, COMMAND_POOL_NODE **cp_state) { 56749a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *cp_state = GetCommandPoolNode(dev_data, pool); 5675cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_command_pool) return false; 56765f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis bool skip = false; 56775f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis if (*cp_state) { 56785f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis // Verify that command buffers in pool are complete (not in-flight) 56795f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis skip |= checkCommandBuffersInFlight(dev_data, *cp_state, "destroy command pool with", VALIDATION_ERROR_00077); 56805f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis } 56815f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis return skip; 56825f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis} 56835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 56845f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlisstatic void PostCallRecordDestroyCommandPool(layer_data *dev_data, VkCommandPool pool, COMMAND_POOL_NODE *cp_state) { 56859f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis // Must remove cmdpool from cmdpoolmap, after removing all cmdbuffers in its list from the commandBufferMap 56865f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis clearCommandBuffersInFlight(dev_data, cp_state); 56875f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis for (auto cb : cp_state->commandBuffers) { 56889a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, cb); 56897b34d10b918c1f69e7252174965c6a7a7c35ae05Chris Forbes clear_cmd_buf_and_mem_references(dev_data, cb_node); 5690d61de0e68063faa169a9a632f811c9c9adec9897Tobin Ehlis // Remove references to this cb_node prior to delete 5691d61de0e68063faa169a9a632f811c9c9adec9897Tobin Ehlis // TODO : Need better solution here, resetCB? 56927165385f3a39f1f951f3a6a9a06ed2cce4642b6dMark Lobodzinski for (auto obj : cb_node->object_bindings) { 56937165385f3a39f1f951f3a6a9a06ed2cce4642b6dMark Lobodzinski removeCommandBufferBinding(dev_data, &obj, cb_node); 56947165385f3a39f1f951f3a6a9a06ed2cce4642b6dMark Lobodzinski } 5695d61de0e68063faa169a9a632f811c9c9adec9897Tobin Ehlis for (auto framebuffer : cb_node->framebuffers) { 56969a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto fb_state = GetFramebufferState(dev_data, framebuffer); 5697cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (fb_state) fb_state->cb_bindings.erase(cb_node); 5698d61de0e68063faa169a9a632f811c9c9adec9897Tobin Ehlis } 5699cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski dev_data->commandBufferMap.erase(cb); // Remove this command buffer 5700cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski delete cb_node; // delete CB info structure 5701a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes } 57025f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis dev_data->commandPoolMap.erase(pool); 57035f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis} 5704e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis 57055f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis// Destroy commandPool along with all of the commandBuffers allocated from that pool 57065f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin EhlisVKAPI_ATTR void VKAPI_CALL DestroyCommandPool(VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks *pAllocator) { 570756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 57085f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis COMMAND_POOL_NODE *cp_state = nullptr; 57095f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 57105f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis bool skip = PreCallValidateDestroyCommandPool(dev_data, commandPool, &cp_state); 57115f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis if (!skip) { 57125f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis lock.unlock(); 57135f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis dev_data->dispatch_table.DestroyCommandPool(device, commandPool, pAllocator); 57145f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis lock.lock(); 5715405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (commandPool != VK_NULL_HANDLE) { 5716405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyCommandPool(dev_data, commandPool, cp_state); 5717405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 57185f9c0dbd099bd351bc564e0f05170ceeadcc995dTobin Ehlis } 57195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 57205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5721bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL ResetCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolResetFlags flags) { 572256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 57233251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 5724400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis 57251ec6311a8537f4467db08eacbd762ebaa87e70b0Chris Forbes std::unique_lock<std::mutex> lock(global_lock); 57269a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pPool = GetCommandPoolNode(dev_data, commandPool); 57273251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= checkCommandBuffersInFlight(dev_data, pPool, "reset command pool with", VALIDATION_ERROR_00072); 57281ec6311a8537f4467db08eacbd762ebaa87e70b0Chris Forbes lock.unlock(); 5729a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes 57303251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 57315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 57324a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.ResetCommandPool(device, commandPool, flags); 57335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 57345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Reset all of the CBs allocated from this pool 57355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 57361ec6311a8537f4467db08eacbd762ebaa87e70b0Chris Forbes lock.lock(); 5737a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes clearCommandBuffersInFlight(dev_data, pPool); 5738a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes for (auto cmdBuffer : pPool->commandBuffers) { 5739a01b5eb150981aad061238e64b173d0da8c11140Chris Forbes resetCB(dev_data, cmdBuffer); 57405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 57411ec6311a8537f4467db08eacbd762ebaa87e70b0Chris Forbes lock.unlock(); 57425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 57435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 57445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 57455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 574689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL ResetFences(VkDevice device, uint32_t fenceCount, const VkFence *pFences) { 574756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 57483251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 5749b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 57505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < fenceCount; ++i) { 57519a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pFence = GetFenceNode(dev_data, pFences[i]); 5752090da73358f71ba026e2474a822fecf55267d166Chris Forbes if (pFence && pFence->state == FENCE_INFLIGHT) { 57533251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, 57543251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<const uint64_t &>(pFences[i]), __LINE__, VALIDATION_ERROR_00183, "DS", 57553251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Fence 0x%" PRIx64 " is in use. %s", reinterpret_cast<const uint64_t &>(pFences[i]), 57563251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski validation_error_map[VALIDATION_ERROR_00183]); 57575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 57585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5759b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 5760090da73358f71ba026e2474a822fecf55267d166Chris Forbes 57613251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 5762090da73358f71ba026e2474a822fecf55267d166Chris Forbes 57634a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.ResetFences(device, fenceCount, pFences); 5764090da73358f71ba026e2474a822fecf55267d166Chris Forbes 5765090da73358f71ba026e2474a822fecf55267d166Chris Forbes if (result == VK_SUCCESS) { 5766090da73358f71ba026e2474a822fecf55267d166Chris Forbes lock.lock(); 5767090da73358f71ba026e2474a822fecf55267d166Chris Forbes for (uint32_t i = 0; i < fenceCount; ++i) { 57689a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pFence = GetFenceNode(dev_data, pFences[i]); 5769090da73358f71ba026e2474a822fecf55267d166Chris Forbes if (pFence) { 5770090da73358f71ba026e2474a822fecf55267d166Chris Forbes pFence->state = FENCE_UNSIGNALED; 5771090da73358f71ba026e2474a822fecf55267d166Chris Forbes } 5772090da73358f71ba026e2474a822fecf55267d166Chris Forbes } 5773090da73358f71ba026e2474a822fecf55267d166Chris Forbes lock.unlock(); 5774090da73358f71ba026e2474a822fecf55267d166Chris Forbes } 5775090da73358f71ba026e2474a822fecf55267d166Chris Forbes 57765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 57775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 57785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5779e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis// For given cb_nodes, invalidate them and track object causing invalidation 57800a4087f99558069e9f6a437ff2dbb5a9c1c22ccaTobin Ehlisvoid invalidateCommandBuffers(const layer_data *dev_data, std::unordered_set<GLOBAL_CB_NODE *> const &cb_nodes, VK_OBJECT obj) { 5781e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis for (auto cb_node : cb_nodes) { 578239c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis if (cb_node->state == CB_RECORDING) { 578339c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 5784fefa20333f94ea75877cca53d0631542cd9d0432Tobin Ehlis (uint64_t)(cb_node->commandBuffer), __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER, "DS", 5785226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "Invalidating a command buffer that's currently being recorded: 0x%p.", cb_node->commandBuffer); 578639c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis } 5787e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis cb_node->state = CB_INVALID; 5788e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis cb_node->broken_bindings.push_back(obj); 5789e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis } 5790e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis} 5791e1cc7cf9e8a7808209ecc45df2421f3a494dacccTobin Ehlis 5792c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlisstatic bool PreCallValidateDestroyFramebuffer(layer_data *dev_data, VkFramebuffer framebuffer, 5793c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis FRAMEBUFFER_STATE **framebuffer_state, VK_OBJECT *obj_struct) { 57949a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *framebuffer_state = GetFramebufferState(dev_data, framebuffer); 57957a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski *obj_struct = {reinterpret_cast<uint64_t &>(framebuffer), kVulkanObjectTypeFramebuffer}; 5796cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_framebuffer) return false; 5797728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis bool skip = false; 5798728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis if (*framebuffer_state) { 5799728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis skip |= ValidateObjectNotInUse(dev_data, *framebuffer_state, *obj_struct, VALIDATION_ERROR_00422); 5800728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis } 5801728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis return skip; 5802728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis} 5803728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis 5804c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlisstatic void PostCallRecordDestroyFramebuffer(layer_data *dev_data, VkFramebuffer framebuffer, FRAMEBUFFER_STATE *framebuffer_state, 5805728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis VK_OBJECT obj_struct) { 580639c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis invalidateCommandBuffers(dev_data, framebuffer_state->cb_bindings, obj_struct); 5807728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis dev_data->frameBufferMap.erase(framebuffer); 5808728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis} 5809728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis 5810bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyFramebuffer(VkDevice device, VkFramebuffer framebuffer, const VkAllocationCallbacks *pAllocator) { 581156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 5812c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis FRAMEBUFFER_STATE *framebuffer_state = nullptr; 5813728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis VK_OBJECT obj_struct; 5814b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 5815728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis bool skip = PreCallValidateDestroyFramebuffer(dev_data, framebuffer, &framebuffer_state, &obj_struct); 5816728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis if (!skip) { 5817728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis lock.unlock(); 5818728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis dev_data->dispatch_table.DestroyFramebuffer(device, framebuffer, pAllocator); 5819728a3e68af2277743cc59185dab7281e96480efeTobin Ehlis lock.lock(); 5820405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (framebuffer != VK_NULL_HANDLE) { 5821405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyFramebuffer(dev_data, framebuffer, framebuffer_state, obj_struct); 5822405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 58235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 58245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 58255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 58260ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlisstatic bool PreCallValidateDestroyRenderPass(layer_data *dev_data, VkRenderPass render_pass, RENDER_PASS_STATE **rp_state, 58270ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis VK_OBJECT *obj_struct) { 58289a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *rp_state = GetRenderPassState(dev_data, render_pass); 58297a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski *obj_struct = {reinterpret_cast<uint64_t &>(render_pass), kVulkanObjectTypeRenderPass}; 5830cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.destroy_renderpass) return false; 58310ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis bool skip = false; 58320ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis if (*rp_state) { 58330ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis skip |= ValidateObjectNotInUse(dev_data, *rp_state, *obj_struct, VALIDATION_ERROR_00393); 58340ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis } 58350ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis return skip; 58360ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis} 58370ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis 58380ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlisstatic void PostCallRecordDestroyRenderPass(layer_data *dev_data, VkRenderPass render_pass, RENDER_PASS_STATE *rp_state, 58390ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis VK_OBJECT obj_struct) { 584039c845ed4c066740e9efaed0a00af51be07c67c1Tobin Ehlis invalidateCommandBuffers(dev_data, rp_state->cb_bindings, obj_struct); 58410ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis dev_data->renderPassMap.erase(render_pass); 58420ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis} 58430ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis 5844bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyRenderPass(VkDevice device, VkRenderPass renderPass, const VkAllocationCallbacks *pAllocator) { 584556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 58460ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis RENDER_PASS_STATE *rp_state = nullptr; 58470ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis VK_OBJECT obj_struct; 5848e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 58490ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis bool skip = PreCallValidateDestroyRenderPass(dev_data, renderPass, &rp_state, &obj_struct); 5850a9fbfe0c622e9fa4b56ddd015ed4c3c409020c2eTobin Ehlis if (!skip) { 5851a9fbfe0c622e9fa4b56ddd015ed4c3c409020c2eTobin Ehlis lock.unlock(); 58524a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyRenderPass(device, renderPass, pAllocator); 58530ffd03853dc28123fa113e6cd49264838559ee39Tobin Ehlis lock.lock(); 5854405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (renderPass != VK_NULL_HANDLE) { 5855405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour PostCallRecordDestroyRenderPass(dev_data, renderPass, rp_state, obj_struct); 5856405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 5857a9fbfe0c622e9fa4b56ddd015ed4c3c409020c2eTobin Ehlis } 58585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 58595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 586089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateBuffer(VkDevice device, const VkBufferCreateInfo *pCreateInfo, 586189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkBuffer *pBuffer) { 586256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 58633683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski std::unique_lock<std::mutex> lock(global_lock); 58643683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski bool skip = PreCallValidateCreateBuffer(dev_data, pCreateInfo); 58653683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski lock.unlock(); 58663683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski 58673683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 58684a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateBuffer(device, pCreateInfo, pAllocator, pBuffer); 58695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 58705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 58713683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski lock.lock(); 58723683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski PostCallRecordCreateBuffer(dev_data, pCreateInfo, pBuffer); 58733683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski lock.unlock(); 58745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 58755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 58765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 58775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 587889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateBufferView(VkDevice device, const VkBufferViewCreateInfo *pCreateInfo, 587989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkBufferView *pView) { 588056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 58818c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young std::unique_lock<std::mutex> lock(global_lock); 58823251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = PreCallValidateCreateBufferView(dev_data, pCreateInfo); 58838c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young lock.unlock(); 58843251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 58854a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateBufferView(device, pCreateInfo, pAllocator, pView); 58865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 58878c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young lock.lock(); 58883683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski PostCallRecordCreateBufferView(dev_data, pCreateInfo, pView); 58898c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young lock.unlock(); 58905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 58915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 58925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 58935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 58948dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski// Access helper functions for external modules 5895d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinskiconst VkFormatProperties *GetFormatProperties(core_validation::layer_data *device_data, VkFormat format) { 5896d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski VkFormatProperties *format_properties = new VkFormatProperties; 5897d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski instance_layer_data *instance_data = 5898d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski GetLayerDataPtr(get_dispatch_key(device_data->instance_data->instance), instance_layer_data_map); 5899d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski instance_data->dispatch_table.GetPhysicalDeviceFormatProperties(device_data->physical_device, format, format_properties); 5900d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski return format_properties; 59018dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski} 59028dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski 5903d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinskiconst VkImageFormatProperties *GetImageFormatProperties(core_validation::layer_data *device_data, VkFormat format, 5904d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski VkImageType image_type, VkImageTiling tiling, VkImageUsageFlags usage, 5905d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski VkImageCreateFlags flags) { 5906d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski VkImageFormatProperties *image_format_properties = new VkImageFormatProperties; 5907d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski instance_layer_data *instance_data = 5908d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski GetLayerDataPtr(get_dispatch_key(device_data->instance_data->instance), instance_layer_data_map); 5909d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski instance_data->dispatch_table.GetPhysicalDeviceImageFormatProperties(device_data->physical_device, format, image_type, tiling, 5910d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski usage, flags, image_format_properties); 5911d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinski return image_format_properties; 59128dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski} 59138dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski 59147a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlisconst debug_report_data *GetReportData(const core_validation::layer_data *device_data) { return device_data->report_data; } 59158dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski 59168dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinskiconst VkPhysicalDeviceProperties *GetPhysicalDeviceProperties(core_validation::layer_data *device_data) { 59178dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski return &device_data->phys_dev_props; 59188dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski} 59198dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski 59208c59133586421be878d393799b30044497f77727Mark Lobodzinskiconst CHECK_DISABLED *GetDisables(core_validation::layer_data *device_data) { return &device_data->instance_data->disabled; } 59218c59133586421be878d393799b30044497f77727Mark Lobodzinski 59228c59133586421be878d393799b30044497f77727Mark Lobodzinskistd::unordered_map<VkImage, std::unique_ptr<IMAGE_STATE>> *GetImageMap(core_validation::layer_data *device_data) { 59238c59133586421be878d393799b30044497f77727Mark Lobodzinski return &device_data->imageMap; 59248c59133586421be878d393799b30044497f77727Mark Lobodzinski} 59258c59133586421be878d393799b30044497f77727Mark Lobodzinski 59268c59133586421be878d393799b30044497f77727Mark Lobodzinskistd::unordered_map<VkImage, std::vector<ImageSubresourcePair>> *GetImageSubresourceMap(core_validation::layer_data *device_data) { 59278c59133586421be878d393799b30044497f77727Mark Lobodzinski return &device_data->imageSubresourceMap; 59288c59133586421be878d393799b30044497f77727Mark Lobodzinski} 59298c59133586421be878d393799b30044497f77727Mark Lobodzinski 59308c59133586421be878d393799b30044497f77727Mark Lobodzinskistd::unordered_map<ImageSubresourcePair, IMAGE_LAYOUT_NODE> *GetImageLayoutMap(layer_data *device_data) { 59318c59133586421be878d393799b30044497f77727Mark Lobodzinski return &device_data->imageLayoutMap; 59328c59133586421be878d393799b30044497f77727Mark Lobodzinski} 59338c59133586421be878d393799b30044497f77727Mark Lobodzinski 59340db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlisstd::unordered_map<ImageSubresourcePair, IMAGE_LAYOUT_NODE> const *GetImageLayoutMap(layer_data const *device_data) { 59350db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis return &device_data->imageLayoutMap; 59360db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis} 59370db18ab1345f9e10907913b22ea5d57bd48077ebTobin Ehlis 59383683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinskistd::unordered_map<VkBuffer, std::unique_ptr<BUFFER_STATE>> *GetBufferMap(layer_data *device_data) { 59393683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski return &device_data->bufferMap; 59403683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski} 59413683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski 59423683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinskistd::unordered_map<VkBufferView, std::unique_ptr<BUFFER_VIEW_STATE>> *GetBufferViewMap(layer_data *device_data) { 59433683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski return &device_data->bufferViewMap; 59443683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski} 59453683836d93195a82dfd2c715ce9d56b030801598Mark Lobodzinski 59461c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinskistd::unordered_map<VkImageView, std::unique_ptr<IMAGE_VIEW_STATE>> *GetImageViewMap(layer_data *device_data) { 59471c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski return &device_data->imageViewMap; 59481c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski} 59491c143ebdb651ea034e0b1f8731cb9f361e2f8b82Mark Lobodzinski 5950d0b59d0aabea9048c518840e762c7a510927c132Mark Lobodzinskiconst PHYS_DEV_PROPERTIES_NODE *GetPhysDevProperties(const layer_data *device_data) { 59516a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski return &device_data->phys_dev_properties; 59526a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski} 59536a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski 59545f3e7c34de87353f38bbcd79e12de8af4a9e7695Mark Lobodzinskiconst VkPhysicalDeviceFeatures *GetEnabledFeatures(const layer_data *device_data) { 59555f3e7c34de87353f38bbcd79e12de8af4a9e7695Mark Lobodzinski return &device_data->enabled_features; 59565f3e7c34de87353f38bbcd79e12de8af4a9e7695Mark Lobodzinski} 59575f3e7c34de87353f38bbcd79e12de8af4a9e7695Mark Lobodzinski 59580e2296e24065d02615ee87561bbb80af414a1ddfMike Schuchardtconst devExts *GetDeviceExtensions(const layer_data *device_data) { return &device_data->device_extensions; } 59590e2296e24065d02615ee87561bbb80af414a1ddfMike Schuchardt 596089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo, 596189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkImage *pImage) { 59628dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 596356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 59648dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski bool skip = PreCallValidateCreateImage(dev_data, pCreateInfo, pAllocator, pImage); 59658dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski if (!skip) { 59668dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski result = dev_data->dispatch_table.CreateImage(device, pCreateInfo, pAllocator, pImage); 59678dea300c362f709ad26886548ea46eb4c315e401Mark Lobodzinski } 59685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 5969b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 5970920311b6aa5614a545cad59521770d0898a75d65Mark Lobodzinski PostCallRecordCreateImage(dev_data, pCreateInfo, pImage); 59715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 59725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 59735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 59745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 59758c07a094dc9cc4afb6b62181f341c12b9e969041Mark YoungVKAPI_ATTR VkResult VKAPI_CALL CreateImageView(VkDevice device, const VkImageViewCreateInfo *pCreateInfo, 59768c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young const VkAllocationCallbacks *pAllocator, VkImageView *pView) { 597756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 59788c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young std::unique_lock<std::mutex> lock(global_lock); 5979e3effabf8e97cae8e006477806ceaca62e4f2ce7Tobin Ehlis bool skip = PreCallValidateCreateImageView(dev_data, pCreateInfo); 59808c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young lock.unlock(); 5981cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 59824a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateImageView(device, pCreateInfo, pAllocator, pView); 59835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 59848c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young lock.lock(); 598579fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis PostCallRecordCreateImageView(dev_data, pCreateInfo, *pView); 59868c07a094dc9cc4afb6b62181f341c12b9e969041Mark Young lock.unlock(); 59875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 5988bb6624cb996175d8945190886a200e720b3871efChris Forbes 59895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 59905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 59915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 5992bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateFence(VkDevice device, const VkFenceCreateInfo *pCreateInfo, 5993bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkFence *pFence) { 599456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 59954a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateFence(device, pCreateInfo, pAllocator, pFence); 59965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 5997b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 5998a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis auto &fence_node = dev_data->fenceMap[*pFence]; 59998988ad37ea5a054ff2ae3cbe4b767ae6c13cf48bChris Forbes fence_node.fence = *pFence; 6000a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis fence_node.createInfo = *pCreateInfo; 6001cdb1ea0ff0d966dda02543468377eae93b9e2f8fChris Forbes fence_node.state = (pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT) ? FENCE_RETIRED : FENCE_UNSIGNALED; 60025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 60035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 60045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 60055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 60065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis// TODO handle pipeline caches 600789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreatePipelineCache(VkDevice device, const VkPipelineCacheCreateInfo *pCreateInfo, 600889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkPipelineCache *pPipelineCache) { 600956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 60104a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreatePipelineCache(device, pCreateInfo, pAllocator, pPipelineCache); 60115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 60125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 60135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6014bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyPipelineCache(VkDevice device, VkPipelineCache pipelineCache, 6015bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator) { 601656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 60174a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.DestroyPipelineCache(device, pipelineCache, pAllocator); 60185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 60195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6020bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL GetPipelineCacheData(VkDevice device, VkPipelineCache pipelineCache, size_t *pDataSize, 6021bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski void *pData) { 602256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 60234a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.GetPipelineCacheData(device, pipelineCache, pDataSize, pData); 60245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 60255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 60265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6027bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL MergePipelineCaches(VkDevice device, VkPipelineCache dstCache, uint32_t srcCacheCount, 6028bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkPipelineCache *pSrcCaches) { 602956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 60304a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.MergePipelineCaches(device, dstCache, srcCacheCount, pSrcCaches); 60315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 60325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 60335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 60343d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis// utility function to set collective state for pipeline 60354c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlisvoid set_pipeline_state(PIPELINE_STATE *pPipe) { 60363d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis // If any attachment used by this pipeline has blendEnable, set top-level blendEnable 60373d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis if (pPipe->graphicsPipelineCI.pColorBlendState) { 60383d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis for (size_t i = 0; i < pPipe->attachments.size(); ++i) { 60393d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis if (VK_TRUE == pPipe->attachments[i].blendEnable) { 60403d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis if (((pPipe->attachments[i].dstAlphaBlendFactor >= VK_BLEND_FACTOR_CONSTANT_COLOR) && 60413d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis (pPipe->attachments[i].dstAlphaBlendFactor <= VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA)) || 60423d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis ((pPipe->attachments[i].dstColorBlendFactor >= VK_BLEND_FACTOR_CONSTANT_COLOR) && 60433d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis (pPipe->attachments[i].dstColorBlendFactor <= VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA)) || 60443d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis ((pPipe->attachments[i].srcAlphaBlendFactor >= VK_BLEND_FACTOR_CONSTANT_COLOR) && 60453d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis (pPipe->attachments[i].srcAlphaBlendFactor <= VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA)) || 60463d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis ((pPipe->attachments[i].srcColorBlendFactor >= VK_BLEND_FACTOR_CONSTANT_COLOR) && 60473d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis (pPipe->attachments[i].srcColorBlendFactor <= VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA))) { 60483d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis pPipe->blendConstantsEnabled = true; 60493d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 60503d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 60513d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 60523d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis } 60533d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis} 60543d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis 6055daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinskibool validate_dual_src_blend_feature(layer_data *device_data, PIPELINE_STATE *pipe_state) { 6056daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski bool skip = false; 6057daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski if (pipe_state->graphicsPipelineCI.pColorBlendState) { 6058daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski for (size_t i = 0; i < pipe_state->attachments.size(); ++i) { 6059daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski if (!device_data->enabled_features.dualSrcBlend) { 6060daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski if ((pipe_state->attachments[i].dstAlphaBlendFactor == VK_BLEND_FACTOR_SRC1_COLOR) || 6061daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski (pipe_state->attachments[i].dstAlphaBlendFactor == VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR) || 6062daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski (pipe_state->attachments[i].dstAlphaBlendFactor == VK_BLEND_FACTOR_SRC1_ALPHA) || 6063daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski (pipe_state->attachments[i].dstAlphaBlendFactor == VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA) || 6064daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski (pipe_state->attachments[i].srcAlphaBlendFactor == VK_BLEND_FACTOR_SRC1_COLOR) || 6065daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski (pipe_state->attachments[i].srcAlphaBlendFactor == VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR) || 6066daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski (pipe_state->attachments[i].srcAlphaBlendFactor == VK_BLEND_FACTOR_SRC1_ALPHA) || 6067daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski (pipe_state->attachments[i].srcAlphaBlendFactor == VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA)) { 6068daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski skip |= 6069daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 6070daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski reinterpret_cast<uint64_t &>(pipe_state->pipeline), __LINE__, DRAWSTATE_INVALID_FEATURE, "DS", 6071daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski "CmdBindPipeline: vkPipeline (0x%" PRIxLEAST64 ") attachment[" PRINTF_SIZE_T_SPECIFIER 6072daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski "] has a dual-source blend factor but this device feature is not enabled.", 6073daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski reinterpret_cast<uint64_t &>(pipe_state->pipeline), i); 6074daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski } 6075daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski } 6076daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski } 6077daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski } 6078daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski return skip; 6079daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski} 6080daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski 608148b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinskistatic bool PreCallCreateGraphicsPipelines(layer_data *device_data, uint32_t count, 608248b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinski const VkGraphicsPipelineCreateInfo *create_infos, vector<PIPELINE_STATE *> &pipe_state) { 608348b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinski bool skip = false; 6084bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski instance_layer_data *instance_data = 608556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis GetLayerDataPtr(get_dispatch_key(device_data->instance_data->instance), instance_layer_data_map); 608648b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinski 608748b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinski for (uint32_t i = 0; i < count; i++) { 608848b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinski skip |= verifyPipelineCreateState(device_data, pipe_state, i); 608978b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski if (create_infos[i].pVertexInputState != NULL) { 609078b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski for (uint32_t j = 0; j < create_infos[i].pVertexInputState->vertexAttributeDescriptionCount; j++) { 609178b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski VkFormat format = create_infos[i].pVertexInputState->pVertexAttributeDescriptions[j].format; 609278b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski // Internal call to get format info. Still goes through layers, could potentially go directly to ICD. 609378b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski VkFormatProperties properties; 609478b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski instance_data->dispatch_table.GetPhysicalDeviceFormatProperties(device_data->physical_device, format, &properties); 609578b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski if ((properties.bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) == 0) { 609678b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski skip |= log_msg( 609778b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 609878b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski __LINE__, VALIDATION_ERROR_01413, "IMAGE", 609978b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski "vkCreateGraphicsPipelines: pCreateInfo[%d].pVertexInputState->vertexAttributeDescriptions[%d].format " 610078b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski "(%s) is not a supported vertex buffer format. %s", 610178b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski i, j, string_VkFormat(format), validation_error_map[VALIDATION_ERROR_01413]); 610278b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski } 610378b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski } 610478b4bdd8b67f4832a05110431ba3c1ae794391d8Mark Lobodzinski } 610548b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinski } 610648b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinski return skip; 610748b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinski} 610848b8ad74fa1a9e39463afce0cb8376c3e0b691a8Mark Lobodzinski 6109bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count, 6110bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkGraphicsPipelineCreateInfo *pCreateInfos, 6111bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines) { 61125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODO What to do with pipelineCache? 61135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // The order of operations here is a little convoluted but gets the job done 61144c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis // 1. Pipeline create state is first shadowed into PIPELINE_STATE struct 61155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // 2. Create state is then validated (which uses flags setup during shadowing) 61165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // 3. If everything looks good, we'll then create the pipeline and add NODE to pipelineMap 611742486a20f07b16f0c5361cdc00fd789b07b1989aMark Lobodzinski bool skip = false; 61185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODO : Improve this data struct w/ unique_ptrs so cleanup below is automatic 611942486a20f07b16f0c5361cdc00fd789b07b1989aMark Lobodzinski vector<PIPELINE_STATE *> pipe_state(count); 612056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 61215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 61225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t i = 0; 6123b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 61245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 61255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (i = 0; i < count; i++) { 612642486a20f07b16f0c5361cdc00fd789b07b1989aMark Lobodzinski pipe_state[i] = new PIPELINE_STATE; 612742486a20f07b16f0c5361cdc00fd789b07b1989aMark Lobodzinski pipe_state[i]->initGraphicsPipeline(&pCreateInfos[i]); 61289a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis pipe_state[i]->render_pass_ci.initialize(GetRenderPassState(dev_data, pCreateInfos[i].renderPass)->createInfo.ptr()); 612942486a20f07b16f0c5361cdc00fd789b07b1989aMark Lobodzinski pipe_state[i]->pipeline_layout = *getPipelineLayout(dev_data, pCreateInfos[i].layout); 61305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 613142486a20f07b16f0c5361cdc00fd789b07b1989aMark Lobodzinski skip |= PreCallCreateGraphicsPipelines(dev_data, count, pCreateInfos, pipe_state); 61325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6133c70226063be6148056ceeccf835175a1fd59f24fChris Forbes if (skip) { 6134c70226063be6148056ceeccf835175a1fd59f24fChris Forbes for (i = 0; i < count; i++) { 6135c70226063be6148056ceeccf835175a1fd59f24fChris Forbes delete pipe_state[i]; 61361ab616b32d4e5b7d62d4a8c41b0c03ea335ab845Chris Forbes pPipelines[i] = VK_NULL_HANDLE; 6137c70226063be6148056ceeccf835175a1fd59f24fChris Forbes } 61387a456d188475c23b566334be45dc0489b2789653Chris Forbes return VK_ERROR_VALIDATION_FAILED_EXT; 61397a456d188475c23b566334be45dc0489b2789653Chris Forbes } 61407a456d188475c23b566334be45dc0489b2789653Chris Forbes 61417a456d188475c23b566334be45dc0489b2789653Chris Forbes lock.unlock(); 6142bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto result = 6143bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski dev_data->dispatch_table.CreateGraphicsPipelines(device, pipelineCache, count, pCreateInfos, pAllocator, pPipelines); 61447a456d188475c23b566334be45dc0489b2789653Chris Forbes lock.lock(); 61457a456d188475c23b566334be45dc0489b2789653Chris Forbes for (i = 0; i < count; i++) { 614661943a7503bc8594338f3364ef42f1d863486c04Chris Forbes if (pPipelines[i] == VK_NULL_HANDLE) { 614761943a7503bc8594338f3364ef42f1d863486c04Chris Forbes delete pipe_state[i]; 6148bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski } else { 614961943a7503bc8594338f3364ef42f1d863486c04Chris Forbes pipe_state[i]->pipeline = pPipelines[i]; 615061943a7503bc8594338f3364ef42f1d863486c04Chris Forbes dev_data->pipelineMap[pipe_state[i]->pipeline] = pipe_state[i]; 615161943a7503bc8594338f3364ef42f1d863486c04Chris Forbes } 61525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6153c70226063be6148056ceeccf835175a1fd59f24fChris Forbes 61545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 61555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 61565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6157bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count, 6158bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkComputePipelineCreateInfo *pCreateInfos, 6159bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines) { 61600108a1af0b7c6949846e9d71d00bbfb322b6f7caChris Forbes bool skip = false; 61615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 61625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODO : Improve this data struct w/ unique_ptrs so cleanup below is automatic 61634c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis vector<PIPELINE_STATE *> pPipeState(count); 616456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 61655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 61665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t i = 0; 6167b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 61685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (i = 0; i < count; i++) { 61695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODO: Verify compute stage bits 61705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 61715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Create and initialize internal tracking data structure 61724c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis pPipeState[i] = new PIPELINE_STATE; 61734c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis pPipeState[i]->initComputePipeline(&pCreateInfos[i]); 6174c2a5a36d03bbe52f5854a5884346e4a84115e259Tobin Ehlis pPipeState[i]->pipeline_layout = *getPipelineLayout(dev_data, pCreateInfos[i].layout); 61755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 61765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODO: Add Compute Pipeline Verification 6177e446ad08318228362ef35d73e7a0636075cb3636Chris Forbes skip |= validate_compute_pipeline(dev_data, pPipeState[i]); 61780108a1af0b7c6949846e9d71d00bbfb322b6f7caChris Forbes // skip |= verifyPipelineCreateState(dev_data, pPipeState[i]); 61795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 61805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 61817a456d188475c23b566334be45dc0489b2789653Chris Forbes if (skip) { 61825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (i = 0; i < count; i++) { 61835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Clean up any locally allocated data structures 61844c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis delete pPipeState[i]; 6185fcf67c021fdfcbeb12fb04daa9a69ecd7d376c5cChris Forbes pPipelines[i] = VK_NULL_HANDLE; 61865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 61875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return VK_ERROR_VALIDATION_FAILED_EXT; 61885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 61897a456d188475c23b566334be45dc0489b2789653Chris Forbes 61907a456d188475c23b566334be45dc0489b2789653Chris Forbes lock.unlock(); 6191bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto result = 6192bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski dev_data->dispatch_table.CreateComputePipelines(device, pipelineCache, count, pCreateInfos, pAllocator, pPipelines); 61937a456d188475c23b566334be45dc0489b2789653Chris Forbes lock.lock(); 61947a456d188475c23b566334be45dc0489b2789653Chris Forbes for (i = 0; i < count; i++) { 6195fcf67c021fdfcbeb12fb04daa9a69ecd7d376c5cChris Forbes if (pPipelines[i] == VK_NULL_HANDLE) { 6196fcf67c021fdfcbeb12fb04daa9a69ecd7d376c5cChris Forbes delete pPipeState[i]; 6197bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski } else { 6198fcf67c021fdfcbeb12fb04daa9a69ecd7d376c5cChris Forbes pPipeState[i]->pipeline = pPipelines[i]; 6199fcf67c021fdfcbeb12fb04daa9a69ecd7d376c5cChris Forbes dev_data->pipelineMap[pPipeState[i]->pipeline] = pPipeState[i]; 6200fcf67c021fdfcbeb12fb04daa9a69ecd7d376c5cChris Forbes } 62017a456d188475c23b566334be45dc0489b2789653Chris Forbes } 62027a456d188475c23b566334be45dc0489b2789653Chris Forbes 62035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 62045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 62055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 620689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateSampler(VkDevice device, const VkSamplerCreateInfo *pCreateInfo, 620789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkSampler *pSampler) { 620856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 62094a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateSampler(device, pCreateInfo, pAllocator, pSampler); 62105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 6211b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 6212d31a44af6da568692a73201825459689c9431867Tobin Ehlis dev_data->samplerMap[*pSampler] = unique_ptr<SAMPLER_STATE>(new SAMPLER_STATE(pSampler, pCreateInfo)); 62135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 62145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 62155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 62165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 62170c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlisstatic bool PreCallValidateCreateDescriptorSetLayout(layer_data *dev_data, const VkDescriptorSetLayoutCreateInfo *create_info) { 6218cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.create_descriptor_set_layout) return false; 62190c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis return cvdescriptorset::DescriptorSetLayout::ValidateCreateInfo(dev_data->report_data, create_info); 62200c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis} 62210c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis 62220c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlisstatic void PostCallRecordCreateDescriptorSetLayout(layer_data *dev_data, const VkDescriptorSetLayoutCreateInfo *create_info, 62230c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis VkDescriptorSetLayout set_layout) { 62243f1d2ba6852cf6b1bb4e1f06d690293565108e2cTobin Ehlis // TODO: Convert this to unique_ptr to avoid leaks 62250c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis dev_data->descriptorSetLayoutMap[set_layout] = new cvdescriptorset::DescriptorSetLayout(create_info, set_layout); 62260c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis} 62270c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis 6228bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateDescriptorSetLayout(VkDevice device, const VkDescriptorSetLayoutCreateInfo *pCreateInfo, 6229bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, 6230bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDescriptorSetLayout *pSetLayout) { 623156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 62320c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 62330c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 62340c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis bool skip = PreCallValidateCreateDescriptorSetLayout(dev_data, pCreateInfo); 62350c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis if (!skip) { 62360c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis lock.unlock(); 62370c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis result = dev_data->dispatch_table.CreateDescriptorSetLayout(device, pCreateInfo, pAllocator, pSetLayout); 62380c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis if (VK_SUCCESS == result) { 62390c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis lock.lock(); 62400c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis PostCallRecordCreateDescriptorSetLayout(dev_data, pCreateInfo, *pSetLayout); 62410c347fc6b08172b778c259e1a1219a2403495d48Tobin Ehlis } 62425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 62435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 62445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 62455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 62469e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz// Used by CreatePipelineLayout and CmdPushConstants. 62479e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz// Note that the index argument is optional and only used by CreatePipelineLayout. 62489e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultzstatic bool validatePushConstantRange(const layer_data *dev_data, const uint32_t offset, const uint32_t size, 62499e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz const char *caller_name, uint32_t index = 0) { 6250cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.push_constant_range) return false; 62519e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz uint32_t const maxPushConstantsSize = dev_data->phys_dev_properties.properties.limits.maxPushConstantsSize; 62523251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 62539e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz // Check that offset + size don't exceed the max. 62549e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz // Prevent arithetic overflow here by avoiding addition and testing in this order. 62559e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz if ((offset >= maxPushConstantsSize) || (size > maxPushConstantsSize - offset)) { 62569e24d8153ab63bc3ac08b5a1517c203930b5de91Karl 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. 62579e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz if (0 == strcmp(caller_name, "vkCreatePipelineLayout()")) { 6258e420dd92dcfc04f279e98796a49ee26b2c3ddafeTobin Ehlis if (offset >= maxPushConstantsSize) { 62593251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 62603251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski __LINE__, VALIDATION_ERROR_00877, "DS", 62613251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "%s call has push constants index %u with offset %u that " 62623251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "exceeds this device's maxPushConstantSize of %u. %s", 62633251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski caller_name, index, offset, maxPushConstantsSize, validation_error_map[VALIDATION_ERROR_00877]); 6264e420dd92dcfc04f279e98796a49ee26b2c3ddafeTobin Ehlis } 6265e420dd92dcfc04f279e98796a49ee26b2c3ddafeTobin Ehlis if (size > maxPushConstantsSize - offset) { 62663251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 6267df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 6268df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski __LINE__, VALIDATION_ERROR_00880, "DS", 6269cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s call has push constants index %u with offset %u and size %u that " 6270cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "exceeds this device's maxPushConstantSize of %u. %s", 6271e420dd92dcfc04f279e98796a49ee26b2c3ddafeTobin Ehlis caller_name, index, offset, size, maxPushConstantsSize, validation_error_map[VALIDATION_ERROR_00880]); 6272e420dd92dcfc04f279e98796a49ee26b2c3ddafeTobin Ehlis } 62739e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } else if (0 == strcmp(caller_name, "vkCmdPushConstants()")) { 62744527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton if (offset >= maxPushConstantsSize) { 62753251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 62763251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski __LINE__, VALIDATION_ERROR_00991, "DS", 62773251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "%s call has push constants index %u with offset %u that " 62783251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "exceeds this device's maxPushConstantSize of %u. %s", 62793251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski caller_name, index, offset, maxPushConstantsSize, validation_error_map[VALIDATION_ERROR_00991]); 62804527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton } 62814527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton if (size > maxPushConstantsSize - offset) { 62823251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 6283df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 6284df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski __LINE__, VALIDATION_ERROR_00992, "DS", 6285cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s call has push constants index %u with offset %u and size %u that " 6286cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "exceeds this device's maxPushConstantSize of %u. %s", 62874527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton caller_name, index, offset, size, maxPushConstantsSize, validation_error_map[VALIDATION_ERROR_00992]); 62884527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton } 62899e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } else { 62903251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 62913251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski __LINE__, DRAWSTATE_INTERNAL_ERROR, "DS", "%s caller not supported.", caller_name); 62929e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 62939e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 62949e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz // size needs to be non-zero and a multiple of 4. 62959e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz if ((size == 0) || ((size & 0x3) != 0)) { 62969e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz if (0 == strcmp(caller_name, "vkCreatePipelineLayout()")) { 6297891f13be101e95697e5af9503f06da38b0c48f79Tobin Ehlis if (size == 0) { 62983251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 62993251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski __LINE__, VALIDATION_ERROR_00878, "DS", 63003251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "%s call has push constants index %u with " 63013251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "size %u. Size must be greater than zero. %s", 63023251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski caller_name, index, size, validation_error_map[VALIDATION_ERROR_00878]); 6303891f13be101e95697e5af9503f06da38b0c48f79Tobin Ehlis } 6304891f13be101e95697e5af9503f06da38b0c48f79Tobin Ehlis if (size & 0x3) { 63053251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 63063251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski __LINE__, VALIDATION_ERROR_00879, "DS", 63073251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "%s call has push constants index %u with " 63083251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "size %u. Size must be a multiple of 4. %s", 63093251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski caller_name, index, size, validation_error_map[VALIDATION_ERROR_00879]); 6310891f13be101e95697e5af9503f06da38b0c48f79Tobin Ehlis } 63119e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } else if (0 == strcmp(caller_name, "vkCmdPushConstants()")) { 63124527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton if (size == 0) { 63133251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 63143251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski __LINE__, VALIDATION_ERROR_01000, "DS", 63153251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "%s call has push constants index %u with " 63163251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "size %u. Size must be greater than zero. %s", 63173251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski caller_name, index, size, validation_error_map[VALIDATION_ERROR_01000]); 63184527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton } 63194527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton if (size & 0x3) { 63203251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 63213251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski __LINE__, VALIDATION_ERROR_00990, "DS", 63223251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "%s call has push constants index %u with " 63233251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "size %u. Size must be a multiple of 4. %s", 63243251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski caller_name, index, size, validation_error_map[VALIDATION_ERROR_00990]); 63254527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton } 63269e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } else { 63273251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 63283251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski __LINE__, DRAWSTATE_INTERNAL_ERROR, "DS", "%s caller not supported.", caller_name); 63299e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 63309e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 63319e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz // offset needs to be a multiple of 4. 63329e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz if ((offset & 0x3) != 0) { 63339e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz if (0 == strcmp(caller_name, "vkCreatePipelineLayout()")) { 63343251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 63353251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski __LINE__, VALIDATION_ERROR_02521, "DS", 63363251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "%s call has push constants index %u with " 63373251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "offset %u. Offset must be a multiple of 4. %s", 63383251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski caller_name, index, offset, validation_error_map[VALIDATION_ERROR_02521]); 63399e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } else if (0 == strcmp(caller_name, "vkCmdPushConstants()")) { 63403251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 63413251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski __LINE__, VALIDATION_ERROR_00989, "DS", 63423251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "%s call has push constants with " 63433251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "offset %u. Offset must be a multiple of 4. %s", 63443251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski caller_name, offset, validation_error_map[VALIDATION_ERROR_00989]); 63459e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } else { 63463251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 63473251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski __LINE__, DRAWSTATE_INTERNAL_ERROR, "DS", "%s caller not supported.", caller_name); 63489e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 63495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 63503251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 63515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 63525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6353bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo, 635489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout) { 63553251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 635656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 6357bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz // TODO : Add checks for VALIDATION_ERRORS 865-870 63589e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz // Push Constant Range checks 635907a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz uint32_t i, j; 63605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (i = 0; i < pCreateInfo->pushConstantRangeCount; ++i) { 63613251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= validatePushConstantRange(dev_data, pCreateInfo->pPushConstantRanges[i].offset, 63623251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski pCreateInfo->pPushConstantRanges[i].size, "vkCreatePipelineLayout()", i); 63639e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz if (0 == pCreateInfo->pPushConstantRanges[i].stageFlags) { 63643251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 63653251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski __LINE__, VALIDATION_ERROR_00882, "DS", "vkCreatePipelineLayout() call has no stageFlags set. %s", 63663251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski validation_error_map[VALIDATION_ERROR_00882]); 63679e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 63689e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 63693251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 637007a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz 6371bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl 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. 637207a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz for (i = 0; i < pCreateInfo->pushConstantRangeCount; ++i) { 637307a398f7c8da45c8286cba4ef33239646ee87dc9Karl Schultz for (j = i + 1; j < pCreateInfo->pushConstantRangeCount; ++j) { 6374bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz if (0 != (pCreateInfo->pPushConstantRanges[i].stageFlags & pCreateInfo->pPushConstantRanges[j].stageFlags)) { 63753251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 63763251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski __LINE__, VALIDATION_ERROR_00871, "DS", 63773251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkCreatePipelineLayout() Duplicate stage flags found in ranges %d and %d. %s", i, j, 63783251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski validation_error_map[VALIDATION_ERROR_00871]); 63799e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 63805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 63815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6382f73b2046273413ea1338dd714d67c39f8e0fa09eChris Forbes 63834a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout); 63845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 6385b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 63865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis PIPELINE_LAYOUT_NODE &plNode = dev_data->pipelineLayoutMap[*pPipelineLayout]; 638769b71d9c89447ec87d823669ee9edbfc58af174aTobin Ehlis plNode.layout = *pPipelineLayout; 6388416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis plNode.set_layouts.resize(pCreateInfo->setLayoutCount); 63895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (i = 0; i < pCreateInfo->setLayoutCount; ++i) { 63909a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis plNode.set_layouts[i] = GetDescriptorSetLayout(dev_data, pCreateInfo->pSetLayouts[i]); 63915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6392416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis plNode.push_constant_ranges.resize(pCreateInfo->pushConstantRangeCount); 63935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (i = 0; i < pCreateInfo->pushConstantRangeCount; ++i) { 6394416bfef833408786b4a17f725b0ed6480bc65120Tobin Ehlis plNode.push_constant_ranges[i] = pCreateInfo->pPushConstantRanges[i]; 63955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 63965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 63975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 63985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 63995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6400bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateDescriptorPool(VkDevice device, const VkDescriptorPoolCreateInfo *pCreateInfo, 6401bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkDescriptorPool *pDescriptorPool) { 640256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 64034a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateDescriptorPool(device, pCreateInfo, pAllocator, pDescriptorPool); 64045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 6405a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis DESCRIPTOR_POOL_STATE *pNewNode = new DESCRIPTOR_POOL_STATE(*pDescriptorPool, pCreateInfo); 64065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (NULL == pNewNode) { 64075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, 64085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (uint64_t)*pDescriptorPool, __LINE__, DRAWSTATE_OUT_OF_MEMORY, "DS", 6409a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis "Out of memory while attempting to allocate DESCRIPTOR_POOL_STATE in vkCreateDescriptorPool()")) 64105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return VK_ERROR_VALIDATION_FAILED_EXT; 64115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 6412b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 64135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->descriptorPoolMap[*pDescriptorPool] = pNewNode; 64145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 64155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 64165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Need to do anything if pool create fails? 64175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 64185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 64195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 64205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6421bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL ResetDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, 6422bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDescriptorPoolResetFlags flags) { 64237286e20c06011d3c6fa7edfbdbadd42bb6e8cc35Tobin Ehlis // TODO : Add checks for VALIDATION_ERROR_00928 642456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 64254a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.ResetDescriptorPool(device, descriptorPool, flags); 64265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 6427b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 64285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis clearDescriptorPool(dev_data, device, descriptorPool, flags); 64295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 64305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 64315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 64322c4e180a4442f968b44f3d5136f7ffda706f6428Chris Forbes// Ensure the pool contains enough descriptors and descriptor sets to satisfy 6433789832b514862c7a7b5b847eeb8e7cacb733b77bTobin Ehlis// an allocation request. Fills common_data with the total number of descriptors of each type required, 6434789832b514862c7a7b5b847eeb8e7cacb733b77bTobin Ehlis// as well as DescriptorSetLayout ptrs used for later update. 64357f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlisstatic bool PreCallValidateAllocateDescriptorSets(layer_data *dev_data, const VkDescriptorSetAllocateInfo *pAllocateInfo, 64367f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlis cvdescriptorset::AllocateDescriptorSetsData *common_data) { 64377a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis // Always update common data 64387a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis cvdescriptorset::UpdateAllocateDescriptorSetsData(dev_data, pAllocateInfo, common_data); 6439cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.allocate_descriptor_sets) return false; 64407e73e5c6b3020b96a821985f73012f2af0f1b992Tobin Ehlis // All state checks for AllocateDescriptorSets is done in single function 64417a7c05af97a73fc6d4917ddda909f119583ff9fcTobin Ehlis return cvdescriptorset::ValidateAllocateDescriptorSets(dev_data, pAllocateInfo, common_data); 64427e73e5c6b3020b96a821985f73012f2af0f1b992Tobin Ehlis} 64437e73e5c6b3020b96a821985f73012f2af0f1b992Tobin Ehlis// Allocation state was good and call down chain was made so update state based on allocating descriptor sets 64447e73e5c6b3020b96a821985f73012f2af0f1b992Tobin Ehlisstatic void PostCallRecordAllocateDescriptorSets(layer_data *dev_data, const VkDescriptorSetAllocateInfo *pAllocateInfo, 64457f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlis VkDescriptorSet *pDescriptorSets, 64467f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlis const cvdescriptorset::AllocateDescriptorSetsData *common_data) { 64477e73e5c6b3020b96a821985f73012f2af0f1b992Tobin Ehlis // All the updates are contained in a single cvdescriptorset function 64482c59c1d90b22aa759d785e4233e468616990ff92Tobin Ehlis cvdescriptorset::PerformAllocateDescriptorSets(pAllocateInfo, pDescriptorSets, common_data, &dev_data->descriptorPoolMap, 6449b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis &dev_data->setMap, dev_data); 64502c4e180a4442f968b44f3d5136f7ffda706f6428Chris Forbes} 64512c4e180a4442f968b44f3d5136f7ffda706f6428Chris Forbes 6452bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL AllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo *pAllocateInfo, 6453bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDescriptorSet *pDescriptorSets) { 645456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 6455b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 64567f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlis cvdescriptorset::AllocateDescriptorSetsData common_data(pAllocateInfo->descriptorSetCount); 64573251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = PreCallValidateAllocateDescriptorSets(dev_data, pAllocateInfo, &common_data); 6458b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 6459d173e0daab123373ce75105f2a908f6ae7cef6abChris Forbes 64603251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 6461d173e0daab123373ce75105f2a908f6ae7cef6abChris Forbes 64624a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.AllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets); 64636511ce241f7f210211e0c0e882f3c14889071f4dChris Forbes 64645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 6465b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.lock(); 64667f61868b44f1da1dfa6a4ff726020411db92ce0dTobin Ehlis PostCallRecordAllocateDescriptorSets(dev_data, pAllocateInfo, pDescriptorSets, &common_data); 6467b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 64685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 64695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 64705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 6471cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis// Verify state before freeing DescriptorSets 6472cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlisstatic bool PreCallValidateFreeDescriptorSets(const layer_data *dev_data, VkDescriptorPool pool, uint32_t count, 6473cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis const VkDescriptorSet *descriptor_sets) { 6474cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.free_descriptor_sets) return false; 64753251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 6476cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis // First make sure sets being destroyed are not currently in-use 6477405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour for (uint32_t i = 0; i < count; ++i) { 6478405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (descriptor_sets[i] != VK_NULL_HANDLE) { 64793251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= validateIdleDescriptorSet(dev_data, descriptor_sets[i], "vkFreeDescriptorSets"); 6480405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 6481405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 6482cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis 64839a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DESCRIPTOR_POOL_STATE *pool_state = GetDescriptorPoolState(dev_data, pool); 6484a21f0d8ac8389dc4e23749efc02d82a7ec1eaee3Tobin Ehlis if (pool_state && !(VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT & pool_state->createInfo.flags)) { 6485cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis // Can't Free from a NON_FREE pool 64863251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, 64873251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t &>(pool), __LINE__, VALIDATION_ERROR_00922, "DS", 64883251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "It is invalid to call vkFreeDescriptorSets() with a pool created without setting " 64893251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT. %s", 64903251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski validation_error_map[VALIDATION_ERROR_00922]); 6491cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis } 64923251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 6493cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis} 6494cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis// Sets have been removed from the pool so update underlying state 6495cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlisstatic void PostCallRecordFreeDescriptorSets(layer_data *dev_data, VkDescriptorPool pool, uint32_t count, 6496cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis const VkDescriptorSet *descriptor_sets) { 64979a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DESCRIPTOR_POOL_STATE *pool_state = GetDescriptorPoolState(dev_data, pool); 6498cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis // Update available descriptor sets in pool 6499cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis pool_state->availableSets += count; 6500cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis 6501cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis // For each freed descriptor add its resources back into the pool as available and remove from pool and setMap 6502cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis for (uint32_t i = 0; i < count; ++i) { 6503405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour if (descriptor_sets[i] != VK_NULL_HANDLE) { 6504405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour auto descriptor_set = dev_data->setMap[descriptor_sets[i]]; 6505405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour uint32_t type_index = 0, descriptor_count = 0; 6506405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour for (uint32_t j = 0; j < descriptor_set->GetBindingCount(); ++j) { 6507405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour type_index = static_cast<uint32_t>(descriptor_set->GetTypeFromIndex(j)); 6508405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour descriptor_count = descriptor_set->GetDescriptorCountFromIndex(j); 6509405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour pool_state->availableDescriptorTypeCount[type_index] += descriptor_count; 6510405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 6511405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour freeDescriptorSet(dev_data, descriptor_set); 6512405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour pool_state->sets.erase(descriptor_set); 6513405404ef7f928520a56949bcc4c62f6a337514a9Tony Barbour } 6514cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis } 6515cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis} 65165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6517bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL FreeDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool, uint32_t count, 6518bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkDescriptorSet *pDescriptorSets) { 651956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 65205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Make sure that no sets being destroyed are in-flight 6521b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 65223251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = PreCallValidateFreeDescriptorSets(dev_data, descriptorPool, count, pDescriptorSets); 6523b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 6524e1a3be272f365a7d75f9cc1338d2eebafbf1e6cdTobin Ehlis 65253251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 65264a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.FreeDescriptorSets(device, descriptorPool, count, pDescriptorSets); 65275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 6528b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.lock(); 6529cd53549dd5a597894f308b4bb993c02ae30817d6Tobin Ehlis PostCallRecordFreeDescriptorSets(dev_data, descriptorPool, count, pDescriptorSets); 6530b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 65315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 65325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 65335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 65346b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis// TODO : This is a Proof-of-concept for core validation architecture 65356b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis// Really we'll want to break out these functions to separate files but 65366b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis// keeping it all together here to prove out design 65376b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis// PreCallValidate* handles validating all of the state prior to calling down chain to UpdateDescriptorSets() 65386b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlisstatic bool PreCallValidateUpdateDescriptorSets(layer_data *dev_data, uint32_t descriptorWriteCount, 65396b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis const VkWriteDescriptorSet *pDescriptorWrites, uint32_t descriptorCopyCount, 65406b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis const VkCopyDescriptorSet *pDescriptorCopies) { 6541cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (dev_data->instance_data->disabled.update_descriptor_sets) return false; 65426b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis // First thing to do is perform map look-ups. 65436b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis // NOTE : UpdateDescriptorSets is somewhat unique in that it's operating on a number of DescriptorSets 65446b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis // so we can't just do a single map look-up up-front, but do them individually in functions below 65456b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis 65466b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis // Now make call(s) that validate state, but don't perform state updates in this function 65476b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis // Note, here DescriptorSets is unique in that we don't yet have an instance. Using a helper function in the 65486b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis // namespace which will parse params and make calls into specific class instances 6549104ab082916e41467ef60baaab7a5a8b2e02c59cTobin Ehlis return cvdescriptorset::ValidateUpdateDescriptorSets(dev_data->report_data, dev_data, descriptorWriteCount, pDescriptorWrites, 6550104ab082916e41467ef60baaab7a5a8b2e02c59cTobin Ehlis descriptorCopyCount, pDescriptorCopies); 65516b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis} 65526b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis// PostCallRecord* handles recording state updates following call down chain to UpdateDescriptorSets() 65536b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlisstatic void PostCallRecordUpdateDescriptorSets(layer_data *dev_data, uint32_t descriptorWriteCount, 65546b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis const VkWriteDescriptorSet *pDescriptorWrites, uint32_t descriptorCopyCount, 65556b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis const VkCopyDescriptorSet *pDescriptorCopies) { 6556104ab082916e41467ef60baaab7a5a8b2e02c59cTobin Ehlis cvdescriptorset::PerformUpdateDescriptorSets(dev_data, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, 65576b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis pDescriptorCopies); 65586b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis} 65595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6560bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL UpdateDescriptorSets(VkDevice device, uint32_t descriptorWriteCount, 6561bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkWriteDescriptorSet *pDescriptorWrites, uint32_t descriptorCopyCount, 6562bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkCopyDescriptorSet *pDescriptorCopies) { 65636b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis // Only map look-up at top level is for device-level layer_data 656456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 6565b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 65663251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = PreCallValidateUpdateDescriptorSets(dev_data, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, 65673251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski pDescriptorCopies); 6568b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 65693251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) { 65704a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.UpdateDescriptorSets(device, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, 65714a0754042cf090e131e9e769d8a3633c228625beChris Forbes pDescriptorCopies); 65726b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis lock.lock(); 65736b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis // Since UpdateDescriptorSets() is void, nothing to check prior to updating state 65746b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis PostCallRecordUpdateDescriptorSets(dev_data, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, 65756b67c2aac9862a21e0dd068966c8b0b3aaf0bafdTobin Ehlis pDescriptorCopies); 65765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 65775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 65785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6579bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL AllocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo *pCreateInfo, 6580bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkCommandBuffer *pCommandBuffer) { 658156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 65824a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.AllocateCommandBuffers(device, pCreateInfo, pCommandBuffer); 65835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 6584b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 65859a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pPool = GetCommandPoolNode(dev_data, pCreateInfo->commandPool); 6586cd9a648074f67a1d44c15a056b90fc66da8ead17Chris Forbes 6587cd9a648074f67a1d44c15a056b90fc66da8ead17Chris Forbes if (pPool) { 658872d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis for (uint32_t i = 0; i < pCreateInfo->commandBufferCount; i++) { 65895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Add command buffer to its commandPool map 6590cd9a648074f67a1d44c15a056b90fc66da8ead17Chris Forbes pPool->commandBuffers.push_back(pCommandBuffer[i]); 65915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis GLOBAL_CB_NODE *pCB = new GLOBAL_CB_NODE; 65925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Add command buffer to map 65935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->commandBufferMap[pCommandBuffer[i]] = pCB; 65945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis resetCB(dev_data, pCommandBuffer[i]); 65955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->createInfo = *pCreateInfo; 65965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->device = device; 65975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 65985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6599b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 66005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 66015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 66025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 66035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6604883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis// Add bindings between the given cmd buffer & framebuffer and the framebuffer's children 6605c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlisstatic void AddFramebufferBinding(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, FRAMEBUFFER_STATE *fb_state) { 66060245b74a083d2cb3b083571deb0fe13b4ab428a4Tobin Ehlis addCommandBufferBinding(&fb_state->cb_bindings, 66077a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski {reinterpret_cast<uint64_t &>(fb_state->framebuffer), kVulkanObjectTypeFramebuffer}, 66080245b74a083d2cb3b083571deb0fe13b4ab428a4Tobin Ehlis cb_state); 6609883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis for (auto attachment : fb_state->attachments) { 6610883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis auto view_state = attachment.view_state; 6611883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis if (view_state) { 661203ea795b83fdf0099594808a1a57064dea7f02a1Tobin Ehlis AddCommandBufferBindingImageView(dev_data, cb_state, view_state); 6613883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis } 66149a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto rp_state = GetRenderPassState(dev_data, fb_state->createInfo.renderPass); 6615883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis if (rp_state) { 6616883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis addCommandBufferBinding( 6617883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis &rp_state->cb_bindings, 66187a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski {reinterpret_cast<uint64_t &>(rp_state->renderPass), kVulkanObjectTypeRenderPass}, cb_state); 6619883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis } 6620883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis } 6621883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis} 6622883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis 6623bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL BeginCommandBuffer(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo *pBeginInfo) { 66243251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 662556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 6626b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 66275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Validate command buffer level 66289a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *cb_node = GetCBNode(dev_data, commandBuffer); 6629f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis if (cb_node) { 66305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // This implicitly resets the Cmd Buffer so make sure any fence is done and then clear memory references 6631a265a8ed3bbb32ade305b1be3148d6001a870b76Tobin Ehlis if (dev_data->globalInFlightCmdBuffers.count(commandBuffer)) { 66323251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 66333251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski (uint64_t)commandBuffer, __LINE__, VALIDATION_ERROR_00103, "MEM", 66343251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Calling vkBeginCommandBuffer() on active command buffer 0x%p before it has completed. " 66353251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "You must check command buffer fence before this call. %s", 66363251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski commandBuffer, validation_error_map[VALIDATION_ERROR_00103]); 66375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6638f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis clear_cmd_buf_and_mem_references(dev_data, cb_node); 6639f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis if (cb_node->createInfo.level != VK_COMMAND_BUFFER_LEVEL_PRIMARY) { 66405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Secondary Command Buffer 66415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkCommandBufferInheritanceInfo *pInfo = pBeginInfo->pInheritanceInfo; 66425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!pInfo) { 66433251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 66445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 66454527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton reinterpret_cast<uint64_t>(commandBuffer), __LINE__, VALIDATION_ERROR_00106, "DS", 6646bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "vkBeginCommandBuffer(): Secondary Command Buffer (0x%p) must have inheritance info. %s", commandBuffer, 6647bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski validation_error_map[VALIDATION_ERROR_00106]); 66485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 66495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pBeginInfo->flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT) { 66502c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis // Object_tracker makes sure these objects are valid 66512c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis assert(pInfo->renderPass); 66522c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis assert(pInfo->framebuffer); 66532c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis string errorString = ""; 66549a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto framebuffer = GetFramebufferState(dev_data, pInfo->framebuffer); 66552c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis if (framebuffer) { 66562c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis if ((framebuffer->createInfo.renderPass != pInfo->renderPass) && 66572c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis !verify_renderpass_compatibility(dev_data, framebuffer->renderPassCreateInfo.ptr(), 66589a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GetRenderPassState(dev_data, pInfo->renderPass)->createInfo.ptr(), 66592c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis errorString)) { 66602c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis // renderPass that framebuffer was created with must be compatible with local renderPass 66613251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 66623251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 66633251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t>(commandBuffer), __LINE__, VALIDATION_ERROR_00112, "DS", 66643251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkBeginCommandBuffer(): Secondary Command " 66653251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Buffer (0x%p) renderPass (0x%" PRIxLEAST64 66663251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski ") is incompatible w/ framebuffer " 66673251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "(0x%" PRIxLEAST64 ") w/ render pass (0x%" PRIxLEAST64 ") due to: %s. %s", 66683251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski commandBuffer, reinterpret_cast<const uint64_t &>(pInfo->renderPass), 66693251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<const uint64_t &>(pInfo->framebuffer), 66703251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t &>(framebuffer->createInfo.renderPass), errorString.c_str(), 66713251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski validation_error_map[VALIDATION_ERROR_00112]); 66725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 66732c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis // Connect this framebuffer and its children to this cmdBuffer 66742c09b45e970dcf95b0e03a2528662a93e0f5dc6fTobin Ehlis AddFramebufferBinding(dev_data, cb_node, framebuffer); 66755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 66765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 66774527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton if ((pInfo->occlusionQueryEnable == VK_FALSE || dev_data->enabled_features.occlusionQueryPrecise == VK_FALSE) && 66785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (pInfo->queryFlags & VK_QUERY_CONTROL_PRECISE_BIT)) { 66793251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 66803251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t>(commandBuffer), 66813251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski __LINE__, VALIDATION_ERROR_00107, "DS", 66823251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkBeginCommandBuffer(): Secondary Command Buffer (0x%p) must not have " 66833251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "VK_QUERY_CONTROL_PRECISE_BIT if occulusionQuery is disabled or the device does not " 66843251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "support precise occlusion queries. %s", 66853251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski commandBuffer, validation_error_map[VALIDATION_ERROR_00107]); 66865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 66875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 66885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pInfo && pInfo->renderPass != VK_NULL_HANDLE) { 66899a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto renderPass = GetRenderPassState(dev_data, pInfo->renderPass); 669016387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes if (renderPass) { 6691fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes if (pInfo->subpass >= renderPass->createInfo.subpassCount) { 66923251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 66933251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)commandBuffer, __LINE__, 66943251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski VALIDATION_ERROR_00111, "DS", 66953251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkBeginCommandBuffer(): Secondary Command Buffers (0x%p) must have a subpass index (%d) " 66963251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "that is less than the number of subpasses (%d). %s", 66973251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski commandBuffer, pInfo->subpass, renderPass->createInfo.subpassCount, 66983251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski validation_error_map[VALIDATION_ERROR_00111]); 66995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 67005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 67015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 67025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6703f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis if (CB_RECORDING == cb_node->state) { 67043251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 67053251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski (uint64_t)commandBuffer, __LINE__, VALIDATION_ERROR_00103, "DS", 67063251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkBeginCommandBuffer(): Cannot call Begin on command buffer (0x%p" 67073251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski ") in the RECORDING state. Must first call vkEndCommandBuffer(). %s", 67083251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski commandBuffer, validation_error_map[VALIDATION_ERROR_00103]); 6709347d4d3139a1e743ed85bd375c20fd35bbe68d74Chris Forbes } else if (CB_RECORDED == cb_node->state || (CB_INVALID == cb_node->state && CMD_END == cb_node->last_cmd)) { 6710f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis VkCommandPool cmdPool = cb_node->createInfo.commandPool; 67119a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pPool = GetCommandPoolNode(dev_data, cmdPool); 6712cd9a648074f67a1d44c15a056b90fc66da8ead17Chris Forbes if (!(VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT & pPool->createFlags)) { 67133251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 67145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 67154527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton (uint64_t)commandBuffer, __LINE__, VALIDATION_ERROR_00105, "DS", 6716226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "Call to vkBeginCommandBuffer() on command buffer (0x%p" 6717414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller ") attempts to implicitly reset cmdBuffer created from command pool (0x%" PRIxLEAST64 67184527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton ") that does NOT have the VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT bit set. %s", 67194527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton commandBuffer, (uint64_t)cmdPool, validation_error_map[VALIDATION_ERROR_00105]); 67205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 67215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis resetCB(dev_data, commandBuffer); 67225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 67235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Set updated state here in case implicit reset occurs above 6724f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->state = CB_RECORDING; 6725f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->beginInfo = *pBeginInfo; 6726f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis if (cb_node->beginInfo.pInheritanceInfo) { 6727f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->inheritanceInfo = *(cb_node->beginInfo.pInheritanceInfo); 6728f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->beginInfo.pInheritanceInfo = &cb_node->inheritanceInfo; 6729888e1d268098177fde4a2263e3d7b7cc415f1debMark Young // If we are a secondary command-buffer and inheriting. Update the items we should inherit. 6730f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis if ((cb_node->createInfo.level != VK_COMMAND_BUFFER_LEVEL_PRIMARY) && 6731f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis (cb_node->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT)) { 67329a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis cb_node->activeRenderPass = GetRenderPassState(dev_data, cb_node->beginInfo.pInheritanceInfo->renderPass); 6733f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->activeSubpass = cb_node->beginInfo.pInheritanceInfo->subpass; 6734350841afb70bf8dcfc3c6ec6b66f0aaa639553a3Tobin Ehlis cb_node->activeFramebuffer = cb_node->beginInfo.pInheritanceInfo->framebuffer; 6735f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->framebuffers.insert(cb_node->beginInfo.pInheritanceInfo->framebuffer); 6736888e1d268098177fde4a2263e3d7b7cc415f1debMark Young } 67375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 67385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6739b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 67403251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (skip) { 67415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return VK_ERROR_VALIDATION_FAILED_EXT; 67425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 67434a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.BeginCommandBuffer(commandBuffer, pBeginInfo); 6744400cff9fad0e19c80f6c9ed1181795d411a4bec5Tobin Ehlis 67455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 67465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 67475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 674889d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL EndCommandBuffer(VkCommandBuffer commandBuffer) { 67493251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 675056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 6751b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 67529a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 67535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 67544527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton if ((VK_COMMAND_BUFFER_LEVEL_PRIMARY == pCB->createInfo.level) || 67554527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton !(pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT)) { 6756fd61966f8d41b5bce15620b70563b7864cbb28feCody Northrop // This needs spec clarification to update valid usage, see comments in PR: 6757fd61966f8d41b5bce15620b70563b7864cbb28feCody Northrop // https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/pull/516#discussion_r63013756 67583251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= insideRenderPass(dev_data, pCB, "vkEndCommandBuffer()", VALIDATION_ERROR_00123); 6759fd61966f8d41b5bce15620b70563b7864cbb28feCody Northrop } 67603251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmd(dev_data, pCB, CMD_END, "vkEndCommandBuffer()"); 67611ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_END); 67625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto query : pCB->activeQueries) { 67633251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 67643251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t>(commandBuffer), __LINE__, VALIDATION_ERROR_00124, "DS", 67653251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Ending command buffer with in progress query: queryPool 0x%" PRIx64 ", index %d. %s", 67663251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski (uint64_t)(query.pool), query.index, validation_error_map[VALIDATION_ERROR_00124]); 67675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 67685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 67693251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) { 6770b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 67710d9453d85335963d6cabfbf400b058dc905ea238Chris Forbes auto result = dev_data->dispatch_table.EndCommandBuffer(commandBuffer); 6772b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.lock(); 67735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 67745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->state = CB_RECORDED; 67755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 67760d9453d85335963d6cabfbf400b058dc905ea238Chris Forbes return result; 67775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 67780d9453d85335963d6cabfbf400b058dc905ea238Chris Forbes return VK_ERROR_VALIDATION_FAILED_EXT; 67795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 67805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 67815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6782bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL ResetCommandBuffer(VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags) { 67833251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 678456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 6785b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 67869a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 67875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkCommandPool cmdPool = pCB->createInfo.commandPool; 67889a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pPool = GetCommandPoolNode(dev_data, cmdPool); 6789cd9a648074f67a1d44c15a056b90fc66da8ead17Chris Forbes if (!(VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT & pPool->createFlags)) { 67903251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 67913251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski (uint64_t)commandBuffer, __LINE__, VALIDATION_ERROR_00093, "DS", 67923251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Attempt to reset command buffer (0x%p) created from command pool (0x%" PRIxLEAST64 67933251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski ") that does NOT have the VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT bit set. %s", 67943251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski commandBuffer, (uint64_t)cmdPool, validation_error_map[VALIDATION_ERROR_00093]); 67955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 67963251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= checkCommandBufferInFlight(dev_data, pCB, "reset", VALIDATION_ERROR_00092); 6797b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 67983251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 67994a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.ResetCommandBuffer(commandBuffer, flags); 68005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 6801b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.lock(); 6802a964cad279f9749cd9ebfc7555247ff3bff26d53Chris Forbes dev_data->globalInFlightCmdBuffers.erase(commandBuffer); 68035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis resetCB(dev_data, commandBuffer); 6804b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 68055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 68065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 68075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 680893c396d566d722dc5c6f438eae212da0e9337ba3Mark Lobodzinski 6809bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBindPipeline(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, 6810bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkPipeline pipeline) { 6811e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis bool skip = false; 681256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 6813b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 68149a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer); 6815e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis if (cb_state) { 6816baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip |= ValidateCmdQueueFlags(dev_data, cb_state, "vkCmdBindPipeline()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, 6817baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt VALIDATION_ERROR_00603); 681829f880e9c3c837307e7a19c0ef7275448d483e04Tobin Ehlis skip |= ValidateCmd(dev_data, cb_state, CMD_BINDPIPELINE, "vkCmdBindPipeline()"); 68191ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(cb_state, CMD_BINDPIPELINE); 6820e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis if ((VK_PIPELINE_BIND_POINT_COMPUTE == pipelineBindPoint) && (cb_state->activeRenderPass)) { 6821e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis skip |= 68225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 68235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (uint64_t)pipeline, __LINE__, DRAWSTATE_INVALID_RENDERPASS_CMD, "DS", 6824414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller "Incorrectly binding compute pipeline (0x%" PRIxLEAST64 ") during active RenderPass (0x%" PRIxLEAST64 ")", 6825e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis (uint64_t)pipeline, (uint64_t)cb_state->activeRenderPass->renderPass); 68265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 68274527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton // TODO: VALIDATION_ERROR_00594 VALIDATION_ERROR_00596 68285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6829e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis PIPELINE_STATE *pipe_state = getPipelineState(dev_data, pipeline); 6830e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis if (pipe_state) { 6831e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis cb_state->lastBound[pipelineBindPoint].pipeline_state = pipe_state; 6832e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis set_cb_pso_status(cb_state, pipe_state); 6833e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis set_pipeline_state(pipe_state); 6834daaf8f4ce66b35b4509bb7a7fdf4256e4f324ba7Mark Lobodzinski skip |= validate_dual_src_blend_feature(dev_data, pipe_state); 68355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 6836e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, 68374527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton (uint64_t)pipeline, __LINE__, VALIDATION_ERROR_00600, "DS", 68384527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton "Attempt to bind Pipeline 0x%" PRIxLEAST64 " that doesn't exist! %s", (uint64_t)(pipeline), 68394527dcafa951a1fa931b258bbcd2d48b283610a7Dave Houlton validation_error_map[VALIDATION_ERROR_00600]); 6840e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis } 6841e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis addCommandBufferBinding(&pipe_state->cb_bindings, 68427a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski {reinterpret_cast<uint64_t &>(pipeline), kVulkanObjectTypePipeline}, cb_state); 6843e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis if (VK_PIPELINE_BIND_POINT_GRAPHICS == pipelineBindPoint) { 6844e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis // Add binding for child renderpass 68459a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto rp_state = GetRenderPassState(dev_data, pipe_state->graphicsPipelineCI.renderPass); 6846e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis if (rp_state) { 6847e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis addCommandBufferBinding( 6848e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis &rp_state->cb_bindings, 68497a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski {reinterpret_cast<uint64_t &>(rp_state->renderPass), kVulkanObjectTypeRenderPass}, cb_state); 6850e92495715edaa63453ce5775bf60f3795df72876Tobin Ehlis } 68515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 68525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6853b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 6854cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdBindPipeline(commandBuffer, pipelineBindPoint, pipeline); 68555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 68565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6857bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetViewport(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, 6858bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkViewport *pViewports) { 68593251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 686056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 6861b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 68629a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 68635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 68643251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetViewport()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_01446); 68653251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmd(dev_data, pCB, CMD_SETVIEWPORTSTATE, "vkCmdSetViewport()"); 68661ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETVIEWPORTSTATE); 6867bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pCB->viewportMask |= ((1u << viewportCount) - 1u) << firstViewport; 68685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6869b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 68703251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdSetViewport(commandBuffer, firstViewport, viewportCount, pViewports); 68715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 68725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6873bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetScissor(VkCommandBuffer commandBuffer, uint32_t firstScissor, uint32_t scissorCount, 6874bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkRect2D *pScissors) { 68753251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 687656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 6877b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 68789a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 68795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 68803251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetScissor()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_01495); 68813251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmd(dev_data, pCB, CMD_SETSCISSORSTATE, "vkCmdSetScissor()"); 68821ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETSCISSORSTATE); 6883bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pCB->scissorMask |= ((1u << scissorCount) - 1u) << firstScissor; 68845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6885b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 68863251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdSetScissor(commandBuffer, firstScissor, scissorCount, pScissors); 68875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 68885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 688989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdSetLineWidth(VkCommandBuffer commandBuffer, float lineWidth) { 68903251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 689156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 6892b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 68939a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 68945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 68953251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetLineWidth()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_01480); 68963251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmd(dev_data, pCB, CMD_SETLINEWIDTHSTATE, "vkCmdSetLineWidth()"); 68971ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETLINEWIDTHSTATE); 68985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->status |= CBSTATUS_LINE_WIDTH_SET; 6899a27508babf63d50aea75883a3702979193c23683Mark Young 69004c0df90de562aa248b524a28b355765d8e3eff25Tobin Ehlis PIPELINE_STATE *pPipeTrav = pCB->lastBound[VK_PIPELINE_BIND_POINT_GRAPHICS].pipeline_state; 6901a27508babf63d50aea75883a3702979193c23683Mark Young if (pPipeTrav != NULL && !isDynamic(pPipeTrav, VK_DYNAMIC_STATE_LINE_WIDTH)) { 69023251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 69033251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t>(commandBuffer), __LINE__, VALIDATION_ERROR_01476, "DS", 69043251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkCmdSetLineWidth called but pipeline was created without VK_DYNAMIC_STATE_LINE_WIDTH " 69053251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "flag. This is undefined behavior and could be ignored. %s", 69063251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski validation_error_map[VALIDATION_ERROR_01476]); 6907a27508babf63d50aea75883a3702979193c23683Mark Young } else { 69083251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= verifyLineWidth(dev_data, DRAWSTATE_INVALID_SET, kVulkanObjectTypeCommandBuffer, 69093251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t &>(commandBuffer), lineWidth); 6910a27508babf63d50aea75883a3702979193c23683Mark Young } 69115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6912b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 69133251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdSetLineWidth(commandBuffer, lineWidth); 69145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 69155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6916bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetDepthBias(VkCommandBuffer commandBuffer, float depthBiasConstantFactor, float depthBiasClamp, 6917bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski float depthBiasSlopeFactor) { 69183251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 691956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 6920b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 69219a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 69225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 69233251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetDepthBias()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_01485); 69243251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmd(dev_data, pCB, CMD_SETDEPTHBIASSTATE, "vkCmdSetDepthBias()"); 6925434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski if ((depthBiasClamp != 0.0) && (!dev_data->enabled_features.depthBiasClamp)) { 69263251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 69273251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t>(commandBuffer), __LINE__, VALIDATION_ERROR_01482, "DS", 69283251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkCmdSetDepthBias(): the depthBiasClamp device feature is disabled: the depthBiasClamp " 69293251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "parameter must be set to 0.0. %s", 69303251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski validation_error_map[VALIDATION_ERROR_01482]); 6931434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski } 69323251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) { 6933434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski UpdateCmdBufferLastCmd(pCB, CMD_SETDEPTHBIASSTATE); 6934434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski pCB->status |= CBSTATUS_DEPTH_BIAS_SET; 6935434c3e2a778a3ca5a0a5414cbedd7c0f20a883b7Mark Lobodzinski } 69365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6937b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 69383251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) 69394a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdSetDepthBias(commandBuffer, depthBiasConstantFactor, depthBiasClamp, depthBiasSlopeFactor); 69405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 69415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 694289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdSetBlendConstants(VkCommandBuffer commandBuffer, const float blendConstants[4]) { 69433251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 694456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 6945b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 69469a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 69475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 69483251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetBlendConstants()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_01553); 69493251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmd(dev_data, pCB, CMD_SETBLENDSTATE, "vkCmdSetBlendConstants()"); 69501ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETBLENDSTATE); 69513d3e06b40a06f099e741b9299efa66bddb69a074Tobin Ehlis pCB->status |= CBSTATUS_BLEND_CONSTANTS_SET; 69525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6953b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 69543251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdSetBlendConstants(commandBuffer, blendConstants); 69555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 69565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6957bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetDepthBounds(VkCommandBuffer commandBuffer, float minDepthBounds, float maxDepthBounds) { 69583251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 695956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 6960b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 69619a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 69625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 69633251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetDepthBounds()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_01509); 69643251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmd(dev_data, pCB, CMD_SETDEPTHBOUNDSSTATE, "vkCmdSetDepthBounds()"); 69651ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETDEPTHBOUNDSSTATE); 69665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->status |= CBSTATUS_DEPTH_BOUNDS_SET; 69675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6968b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 69693251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdSetDepthBounds(commandBuffer, minDepthBounds, maxDepthBounds); 69705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 69715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6972bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetStencilCompareMask(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, 6973bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski uint32_t compareMask) { 69743251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 697556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 6976b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 69779a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 69785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 69793251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetStencilCompareMask()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_01519); 69803251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmd(dev_data, pCB, CMD_SETSTENCILREADMASKSTATE, "vkCmdSetStencilCompareMask()"); 69811ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETSTENCILREADMASKSTATE); 69825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->status |= CBSTATUS_STENCIL_READ_MASK_SET; 69835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6984b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 69853251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdSetStencilCompareMask(commandBuffer, faceMask, compareMask); 69865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 69875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 6988bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetStencilWriteMask(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t writeMask) { 69893251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 699056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 6991b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 69929a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 69935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 69943251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetStencilWriteMask()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_01525); 69953251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmd(dev_data, pCB, CMD_SETSTENCILWRITEMASKSTATE, "vkCmdSetStencilWriteMask()"); 69961ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETSTENCILWRITEMASKSTATE); 69975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->status |= CBSTATUS_STENCIL_WRITE_MASK_SET; 69985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 6999b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 70003251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdSetStencilWriteMask(commandBuffer, faceMask, writeMask); 70015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 70025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7003bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetStencilReference(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t reference) { 70043251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 700556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7006b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 70079a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 70085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 70093251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetStencilReference()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_01531); 70103251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmd(dev_data, pCB, CMD_SETSTENCILREFERENCESTATE, "vkCmdSetStencilReference()"); 70111ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETSTENCILREFERENCESTATE); 70125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->status |= CBSTATUS_STENCIL_REFERENCE_SET; 70135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7014b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 70153251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdSetStencilReference(commandBuffer, faceMask, reference); 70165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 70175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7018bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBindDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, 7019bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkPipelineLayout layout, uint32_t firstSet, uint32_t setCount, 7020bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkDescriptorSet *pDescriptorSets, uint32_t dynamicOffsetCount, 7021bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const uint32_t *pDynamicOffsets) { 7022946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski bool skip = false; 702356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7024b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7025946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer); 7026946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (cb_state) { 7027baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip |= ValidateCmdQueueFlags(dev_data, cb_state, "vkCmdBindDescriptorSets()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, 7028baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt VALIDATION_ERROR_00985); 7029946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ValidateCmd(dev_data, cb_state, CMD_BINDDESCRIPTORSETS, "vkCmdBindDescriptorSets()"); 7030ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski // Track total count of dynamic descriptor types to make sure we have an offset for each one 7031946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski uint32_t total_dynamic_descriptors = 0; 7032946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski string error_string = ""; 7033946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski uint32_t last_set_index = firstSet + setCount - 1; 7034946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (last_set_index >= cb_state->lastBound[pipelineBindPoint].boundDescriptorSets.size()) { 7035946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->lastBound[pipelineBindPoint].boundDescriptorSets.resize(last_set_index + 1); 7036946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->lastBound[pipelineBindPoint].dynamicOffsets.resize(last_set_index + 1); 7037946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski } 7038946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski auto old_final_bound_set = cb_state->lastBound[pipelineBindPoint].boundDescriptorSets[last_set_index]; 7039ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski auto pipeline_layout = getPipelineLayout(dev_data, layout); 7040ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski for (uint32_t set_idx = 0; set_idx < setCount; set_idx++) { 7041ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski cvdescriptorset::DescriptorSet *descriptor_set = GetSetNode(dev_data, pDescriptorSets[set_idx]); 7042ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski if (descriptor_set) { 7043946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->lastBound[pipelineBindPoint].pipeline_layout = *pipeline_layout; 7044946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->lastBound[pipelineBindPoint].boundDescriptorSets[set_idx + firstSet] = descriptor_set; 7045946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 7046946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t)pDescriptorSets[set_idx], __LINE__, 7047946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski DRAWSTATE_NONE, "DS", "Descriptor Set 0x%" PRIxLEAST64 " bound on pipeline %s", 7048946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski (uint64_t)pDescriptorSets[set_idx], string_VkPipelineBindPoint(pipelineBindPoint)); 7049ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski if (!descriptor_set->IsUpdated() && (descriptor_set->GetTotalDescriptorCount() != 0)) { 7050946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, 7051946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t)pDescriptorSets[set_idx], __LINE__, 7052946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski DRAWSTATE_DESCRIPTOR_SET_NOT_UPDATED, "DS", 7053946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "Descriptor Set 0x%" PRIxLEAST64 7054946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski " bound but it was never updated. You may want to either update it or not bind it.", 7055946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski (uint64_t)pDescriptorSets[set_idx]); 7056ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } 7057ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski // Verify that set being bound is compatible with overlapping setLayout of pipelineLayout 705812b7fc342b53fbdd399aae4a85959e37685936acChris Forbes if (!verify_set_layout_compatibility(descriptor_set, pipeline_layout, set_idx + firstSet, error_string)) { 7059946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 7060946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t)pDescriptorSets[set_idx], __LINE__, 7061946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski VALIDATION_ERROR_00974, "DS", 7062946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "descriptorSet #%u being bound is not compatible with overlapping descriptorSetLayout " 7063946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "at index %u of pipelineLayout 0x%" PRIxLEAST64 " due to: %s. %s", 7064946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski set_idx, set_idx + firstSet, reinterpret_cast<uint64_t &>(layout), error_string.c_str(), 7065946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski validation_error_map[VALIDATION_ERROR_00974]); 70665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7067ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski 7068946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski auto set_dynamic_descriptor_count = descriptor_set->GetDynamicDescriptorCount(); 7069ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski 7070946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->lastBound[pipelineBindPoint].dynamicOffsets[firstSet + set_idx].clear(); 7071ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski 7072946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (set_dynamic_descriptor_count) { 7073ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski // First make sure we won't overstep bounds of pDynamicOffsets array 7074946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if ((total_dynamic_descriptors + set_dynamic_descriptor_count) > dynamicOffsetCount) { 7075946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 7076946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t)pDescriptorSets[set_idx], 7077946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski __LINE__, DRAWSTATE_INVALID_DYNAMIC_OFFSET_COUNT, "DS", 7078946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "descriptorSet #%u (0x%" PRIxLEAST64 7079946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski ") requires %u dynamicOffsets, but only %u dynamicOffsets are left in pDynamicOffsets " 7080946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "array. There must be one dynamic offset for each dynamic descriptor being bound.", 7081946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski set_idx, (uint64_t)pDescriptorSets[set_idx], descriptor_set->GetDynamicDescriptorCount(), 7082946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski (dynamicOffsetCount - total_dynamic_descriptors)); 7083ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } else { // Validate and store dynamic offsets with the set 7084ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski // Validate Dynamic Offset Minimums 7085946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski uint32_t cur_dyn_offset = total_dynamic_descriptors; 7086ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski for (uint32_t d = 0; d < descriptor_set->GetTotalDescriptorCount(); d++) { 7087ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski if (descriptor_set->GetTypeFromGlobalIndex(d) == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) { 708816769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton if (SafeModulo( 7089ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski pDynamicOffsets[cur_dyn_offset], 7090ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski dev_data->phys_dev_properties.properties.limits.minUniformBufferOffsetAlignment) != 0) { 7091946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= log_msg( 7092ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 7093ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, VALIDATION_ERROR_00978, "DS", 7094ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski "vkCmdBindDescriptorSets(): pDynamicOffsets[%d] is %d but must be a multiple of " 7095ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski "device limit minUniformBufferOffsetAlignment 0x%" PRIxLEAST64 ". %s", 7096ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski cur_dyn_offset, pDynamicOffsets[cur_dyn_offset], 7097ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski dev_data->phys_dev_properties.properties.limits.minUniformBufferOffsetAlignment, 7098ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski validation_error_map[VALIDATION_ERROR_00978]); 7099ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } 7100ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski cur_dyn_offset++; 7101ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } else if (descriptor_set->GetTypeFromGlobalIndex(d) == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) { 710216769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton if (SafeModulo( 7103ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski pDynamicOffsets[cur_dyn_offset], 7104ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski dev_data->phys_dev_properties.properties.limits.minStorageBufferOffsetAlignment) != 0) { 7105946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= log_msg( 7106ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 7107ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, VALIDATION_ERROR_00978, "DS", 7108ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski "vkCmdBindDescriptorSets(): pDynamicOffsets[%d] is %d but must be a multiple of " 7109ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski "device limit minStorageBufferOffsetAlignment 0x%" PRIxLEAST64 ". %s", 7110ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski cur_dyn_offset, pDynamicOffsets[cur_dyn_offset], 7111ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski dev_data->phys_dev_properties.properties.limits.minStorageBufferOffsetAlignment, 7112ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski validation_error_map[VALIDATION_ERROR_00978]); 7113ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } 7114ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski cur_dyn_offset++; 7115ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } 711672d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis } 7117ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski 7118946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->lastBound[pipelineBindPoint].dynamicOffsets[firstSet + set_idx] = 7119946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski std::vector<uint32_t>(pDynamicOffsets + total_dynamic_descriptors, 7120946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski pDynamicOffsets + total_dynamic_descriptors + set_dynamic_descriptor_count); 7121ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski // Keep running total of dynamic descriptor count to verify at the end 7122946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski total_dynamic_descriptors += set_dynamic_descriptor_count; 712372d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis } 712472d66f0c1639cbaca92459498452d06db32d7aefTobin Ehlis } 7125ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } else { 7126946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= log_msg( 7127ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, 7128ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski (uint64_t)pDescriptorSets[set_idx], __LINE__, DRAWSTATE_INVALID_SET, "DS", 7129ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski "Attempt to bind descriptor set 0x%" PRIxLEAST64 " that doesn't exist!", (uint64_t)pDescriptorSets[set_idx]); 7130ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } 7131946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski UpdateCmdBufferLastCmd(cb_state, CMD_BINDDESCRIPTORSETS); 7132ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski // For any previously bound sets, need to set them to "invalid" if they were disturbed by this update 7133ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski if (firstSet > 0) { // Check set #s below the first bound set 7134ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski for (uint32_t i = 0; i < firstSet; ++i) { 7135946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (cb_state->lastBound[pipelineBindPoint].boundDescriptorSets[i] && 713612b7fc342b53fbdd399aae4a85959e37685936acChris Forbes !verify_set_layout_compatibility(cb_state->lastBound[pipelineBindPoint].boundDescriptorSets[i], 7137946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski pipeline_layout, i, error_string)) { 7138946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= log_msg( 7139ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, 7140ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, 7141946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski (uint64_t)cb_state->lastBound[pipelineBindPoint].boundDescriptorSets[i], __LINE__, DRAWSTATE_NONE, "DS", 7142ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski "DescriptorSet 0x%" PRIxLEAST64 7143ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski " previously bound as set #%u was disturbed by newly bound pipelineLayout (0x%" PRIxLEAST64 ")", 7144946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski (uint64_t)cb_state->lastBound[pipelineBindPoint].boundDescriptorSets[i], i, (uint64_t)layout); 7145946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->lastBound[pipelineBindPoint].boundDescriptorSets[i] = VK_NULL_HANDLE; 71465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 71475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 71485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7149ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski // Check if newly last bound set invalidates any remaining bound sets 7150946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if ((cb_state->lastBound[pipelineBindPoint].boundDescriptorSets.size() - 1) > (last_set_index)) { 7151946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (old_final_bound_set && 715212b7fc342b53fbdd399aae4a85959e37685936acChris Forbes !verify_set_layout_compatibility(old_final_bound_set, pipeline_layout, last_set_index, error_string)) { 7153946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski auto old_set = old_final_bound_set->GetSet(); 7154946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, 7155946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, reinterpret_cast<uint64_t &>(old_set), __LINE__, 7156946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski DRAWSTATE_NONE, "DS", "DescriptorSet 0x%" PRIxLEAST64 7157946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski " previously bound as set #%u is incompatible with set 0x%" PRIxLEAST64 7158946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski " newly bound as set #%u so set #%u and any subsequent sets were " 7159946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "disturbed by newly bound pipelineLayout (0x%" PRIxLEAST64 ")", 7160946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski reinterpret_cast<uint64_t &>(old_set), last_set_index, 7161946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski (uint64_t)cb_state->lastBound[pipelineBindPoint].boundDescriptorSets[last_set_index], 7162946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski last_set_index, last_set_index + 1, (uint64_t)layout); 7163946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->lastBound[pipelineBindPoint].boundDescriptorSets.resize(last_set_index + 1); 7164ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } 7165787f29d93dee194c015789cf61c079504c980572Tobin Ehlis } 7166ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } 7167ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski // dynamicOffsetCount must equal the total number of dynamic descriptors in the sets being bound 7168946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (total_dynamic_descriptors != dynamicOffsetCount) { 7169946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 7170946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski (uint64_t)commandBuffer, __LINE__, VALIDATION_ERROR_00975, "DS", 7171946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "Attempting to bind %u descriptorSets with %u dynamic descriptors, but dynamicOffsetCount " 7172946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "is %u. It should exactly match the number of dynamic descriptors. %s", 7173946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski setCount, total_dynamic_descriptors, dynamicOffsetCount, validation_error_map[VALIDATION_ERROR_00975]); 71745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 71755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7176b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7177946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (!skip) 71784a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdBindDescriptorSets(commandBuffer, pipelineBindPoint, layout, firstSet, setCount, 71794a0754042cf090e131e9e769d8a3633c228625beChris Forbes pDescriptorSets, dynamicOffsetCount, pDynamicOffsets); 71805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 71815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7182bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBindIndexBuffer(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, 7183bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkIndexType indexType) { 7184946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski bool skip = false; 718556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7186593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis // TODO : Somewhere need to verify that IBs have correct usage state flagged 7187b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7188b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski 71899a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto buffer_state = GetBufferState(dev_data, buffer); 71909a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, commandBuffer); 71915cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis if (cb_node && buffer_state) { 7192baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip |= ValidateCmdQueueFlags(dev_data, cb_node, "vkCmdBindIndexBuffer()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_01357); 7193946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ValidateCmd(dev_data, cb_node, CMD_BINDINDEXBUFFER, "vkCmdBindIndexBuffer()"); 7194946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ValidateMemoryIsBoundToBuffer(dev_data, buffer_state, "vkCmdBindIndexBuffer()", VALIDATION_ERROR_02543); 7195ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski std::function<bool()> function = [=]() { 7196ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski return ValidateBufferMemoryIsValid(dev_data, buffer_state, "vkCmdBindIndexBuffer()"); 7197ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski }; 7198ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski cb_node->validate_functions.push_back(function); 7199ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski UpdateCmdBufferLastCmd(cb_node, CMD_BINDINDEXBUFFER); 7200ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski VkDeviceSize offset_align = 0; 7201ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski switch (indexType) { 7202ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski case VK_INDEX_TYPE_UINT16: 7203ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski offset_align = 2; 7204ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski break; 7205ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski case VK_INDEX_TYPE_UINT32: 7206ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski offset_align = 4; 7207ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski break; 7208ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski default: 7209ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski // ParamChecker should catch bad enum, we'll also throw alignment error below if offset_align stays 0 7210ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski break; 72115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7212ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski if (!offset_align || (offset % offset_align)) { 7213df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 7214df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(commandBuffer), __LINE__, DRAWSTATE_VTX_INDEX_ALIGNMENT_ERROR, "DS", 7215946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "vkCmdBindIndexBuffer() offset (0x%" PRIxLEAST64 ") does not fall on alignment (%s) boundary.", offset, 7216946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski string_VkIndexType(indexType)); 7217ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski } 7218ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski cb_node->status |= CBSTATUS_INDEX_BUFFER_BOUND; 7219ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } else { 7220ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis assert(0); 72215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7222b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7223946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdBindIndexBuffer(commandBuffer, buffer, offset, indexType); 72245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 72255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 72265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisvoid updateResourceTracking(GLOBAL_CB_NODE *pCB, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer *pBuffers) { 72275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t end = firstBinding + bindingCount; 72285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB->currentDrawData.buffers.size() < end) { 72295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->currentDrawData.buffers.resize(end); 72305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 72315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < bindingCount; ++i) { 72325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->currentDrawData.buffers[i + firstBinding] = pBuffers[i]; 72335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 72345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 72355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7236e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic inline void updateResourceTrackingOnDraw(GLOBAL_CB_NODE *pCB) { pCB->drawData.push_back(pCB->currentDrawData); } 72375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7238bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBindVertexBuffers(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, 7239bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkBuffer *pBuffers, const VkDeviceSize *pOffsets) { 7240946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski bool skip = false; 724156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7242593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis // TODO : Somewhere need to verify that VBs have correct usage state flagged 7243b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7244b3c2024e0ed61d7f68630d7eb7c8c03100689bb1Mark Lobodzinski 72459a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, commandBuffer); 72469f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis if (cb_node) { 7247baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip |= ValidateCmdQueueFlags(dev_data, cb_node, "vkCmdBindVertexBuffers()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_01423); 7248baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip |= ValidateCmd(dev_data, cb_node, CMD_BINDVERTEXBUFFER, "vkCmdBindVertexBuffers()"); 7249ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski for (uint32_t i = 0; i < bindingCount; ++i) { 7250ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski auto buffer_state = GetBufferState(dev_data, pBuffers[i]); 7251ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski assert(buffer_state); 7252946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ValidateMemoryIsBoundToBuffer(dev_data, buffer_state, "vkCmdBindVertexBuffers()", VALIDATION_ERROR_02546); 7253ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski std::function<bool()> function = [=]() { 7254ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski return ValidateBufferMemoryIsValid(dev_data, buffer_state, "vkCmdBindVertexBuffers()"); 7255ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski }; 7256ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski cb_node->validate_functions.push_back(function); 72575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7258ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski UpdateCmdBufferLastCmd(cb_node, CMD_BINDVERTEXBUFFER); 7259ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski updateResourceTracking(cb_node, firstBinding, bindingCount, pBuffers); 72605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 72617828015969ab31ee01d597f0288cbb124b637fcdMark Lobodzinski assert(0); 72625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7263b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7264946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdBindVertexBuffers(commandBuffer, firstBinding, bindingCount, pBuffers, pOffsets); 72655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 72665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 726725002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski// Expects global_lock to be held by caller 72685569d6457ac22e7d245f3cdee045e71ffbc8b06eTobin Ehlisstatic void MarkStoreImagesAndBuffersAsWritten(layer_data *dev_data, GLOBAL_CB_NODE *pCB) { 72697a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis for (auto imageView : pCB->updateImages) { 72709a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto view_state = GetImageViewState(dev_data, imageView); 7271cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!view_state) continue; 7272249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis 72739a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_state = GetImageState(dev_data, view_state->create_info.image); 72741facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis assert(image_state); 7275e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves std::function<bool()> function = [=]() { 72761facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis SetImageMemoryValid(dev_data, image_state, true); 7277e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves return false; 72787a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis }; 72797a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis pCB->validate_functions.push_back(function); 72807a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis } 72817a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis for (auto buffer : pCB->updateBuffers) { 72829a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto buffer_state = GetBufferState(dev_data, buffer); 72835cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis assert(buffer_state); 7284e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves std::function<bool()> function = [=]() { 72855cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis SetBufferMemoryValid(dev_data, buffer_state, true); 7286e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves return false; 72877a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis }; 72887a3985a8a9d255dcca9f5992ca2262c7e5df41c6Tobin Ehlis pCB->validate_functions.push_back(function); 72895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 72905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 72915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7292ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis// Generic function to handle validation for all CmdDraw* type functions 7293ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool ValidateCmdDrawType(layer_data *dev_data, VkCommandBuffer cmd_buffer, bool indexed, VkPipelineBindPoint bind_point, 7294baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt CMD_TYPE cmd_type, GLOBAL_CB_NODE **cb_state, const char *caller, VkQueueFlags queue_flags, 7295baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt UNIQUE_VALIDATION_ERROR_CODE queue_flag_code, UNIQUE_VALIDATION_ERROR_CODE msg_code, 7296baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt UNIQUE_VALIDATION_ERROR_CODE const dynamic_state_msg_code) { 729758b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis bool skip = false; 72989a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *cb_state = GetCBNode(dev_data, cmd_buffer); 729958b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis if (*cb_state) { 7300baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip |= ValidateCmdQueueFlags(dev_data, *cb_state, caller, queue_flags, queue_flag_code); 7301ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis skip |= ValidateCmd(dev_data, *cb_state, cmd_type, caller); 73024f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes skip |= ValidateDrawState(dev_data, *cb_state, indexed, bind_point, caller, dynamic_state_msg_code); 730325d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis skip |= (VK_PIPELINE_BIND_POINT_GRAPHICS == bind_point) ? outsideRenderPass(dev_data, *cb_state, caller, msg_code) 730425d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis : insideRenderPass(dev_data, *cb_state, caller, msg_code); 730558b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis } 730658b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis return skip; 730758b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis} 730858b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis 730925d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis// Generic function to handle state update for all CmdDraw* and CmdDispatch* type functions 7310ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void UpdateStateCmdDrawDispatchType(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point, 7311ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis CMD_TYPE cmd_type) { 7312ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis UpdateDrawState(dev_data, cb_state, bind_point); 73132f921d33544c162dcb726fc3c7b915e89c02ff24Tobin Ehlis MarkStoreImagesAndBuffersAsWritten(dev_data, cb_state); 73141ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(cb_state, cmd_type); 731525d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis} 731625d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis 7317ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis// Generic function to handle state update for all CmdDraw* type functions 7318ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void UpdateStateCmdDrawType(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point, 7319b68b13ed4952bce61f6ebb0023542660c26b0562Chris Forbes CMD_TYPE cmd_type) { 7320ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis UpdateStateCmdDrawDispatchType(dev_data, cb_state, bind_point, cmd_type); 7321c0b225e42808ba8fada7a2f67ecd662e376ccf15Tobin Ehlis updateResourceTrackingOnDraw(cb_state); 7322b68b13ed4952bce61f6ebb0023542660c26b0562Chris Forbes cb_state->hasDrawCmd = true; 7323ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis} 7324ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis 7325ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool PreCallValidateCmdDraw(layer_data *dev_data, VkCommandBuffer cmd_buffer, bool indexed, VkPipelineBindPoint bind_point, 7326ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis GLOBAL_CB_NODE **cb_state, const char *caller) { 7327baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt return ValidateCmdDrawType(dev_data, cmd_buffer, indexed, bind_point, CMD_DRAW, cb_state, caller, VK_QUEUE_GRAPHICS_BIT, 7328baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt VALIDATION_ERROR_01364, VALIDATION_ERROR_01365, VALIDATION_ERROR_02203); 7329ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis} 7330ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis 7331ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void PostCallRecordCmdDraw(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point) { 7332b68b13ed4952bce61f6ebb0023542660c26b0562Chris Forbes UpdateStateCmdDrawType(dev_data, cb_state, bind_point, CMD_DRAW); 7333c0b225e42808ba8fada7a2f67ecd662e376ccf15Tobin Ehlis} 7334c0b225e42808ba8fada7a2f67ecd662e376ccf15Tobin Ehlis 733589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount, 733689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu uint32_t firstVertex, uint32_t firstInstance) { 733756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 733858b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis GLOBAL_CB_NODE *cb_state = nullptr; 7339b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7340ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis bool skip = PreCallValidateCmdDraw(dev_data, commandBuffer, false, VK_PIPELINE_BIND_POINT_GRAPHICS, &cb_state, "vkCmdDraw()"); 7341b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 734258b923895f7f6be1b7d48bd4ee3e85e0b3dd0c4dTobin Ehlis if (!skip) { 73434a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdDraw(commandBuffer, vertexCount, instanceCount, firstVertex, firstInstance); 7344c0b225e42808ba8fada7a2f67ecd662e376ccf15Tobin Ehlis lock.lock(); 7345ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis PostCallRecordCmdDraw(dev_data, cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS); 7346c0b225e42808ba8fada7a2f67ecd662e376ccf15Tobin Ehlis lock.unlock(); 7347c0b225e42808ba8fada7a2f67ecd662e376ccf15Tobin Ehlis } 73485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 73495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7350ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool PreCallValidateCmdDrawIndexed(layer_data *dev_data, VkCommandBuffer cmd_buffer, bool indexed, 7351ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis VkPipelineBindPoint bind_point, GLOBAL_CB_NODE **cb_state, const char *caller) { 7352baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt return ValidateCmdDrawType(dev_data, cmd_buffer, indexed, bind_point, CMD_DRAWINDEXED, cb_state, caller, VK_QUEUE_GRAPHICS_BIT, 7353baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt VALIDATION_ERROR_01371, VALIDATION_ERROR_01372, VALIDATION_ERROR_02216); 7354ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis} 7355ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis 7356ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void PostCallRecordCmdDrawIndexed(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point) { 7357b68b13ed4952bce61f6ebb0023542660c26b0562Chris Forbes UpdateStateCmdDrawType(dev_data, cb_state, bind_point, CMD_DRAWINDEXED); 7358ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis} 7359ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis 7360bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount, 7361bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance) { 736256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7363ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis GLOBAL_CB_NODE *cb_state = nullptr; 7364b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7365ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis bool skip = PreCallValidateCmdDrawIndexed(dev_data, commandBuffer, true, VK_PIPELINE_BIND_POINT_GRAPHICS, &cb_state, 7366ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis "vkCmdDrawIndexed()"); 7367b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7368ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis if (!skip) { 73694a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdDrawIndexed(commandBuffer, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance); 7370ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis lock.lock(); 7371ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis PostCallRecordCmdDrawIndexed(dev_data, cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS); 7372ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis lock.unlock(); 7373ac4451d7e5da96a3a5d51e613c583c057aee9cf4Tobin Ehlis } 73745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 73755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7376ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool PreCallValidateCmdDrawIndirect(layer_data *dev_data, VkCommandBuffer cmd_buffer, VkBuffer buffer, bool indexed, 7377ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis VkPipelineBindPoint bind_point, GLOBAL_CB_NODE **cb_state, BUFFER_STATE **buffer_state, 7378ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis const char *caller) { 73794f5a71335df5361d740a23b4548d54fc72a28d4fJeremy Hayes bool skip = ValidateCmdDrawType(dev_data, cmd_buffer, indexed, bind_point, CMD_DRAWINDIRECT, cb_state, caller, 7380baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_01380, VALIDATION_ERROR_01381, VALIDATION_ERROR_02234); 73819a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *buffer_state = GetBufferState(dev_data, buffer); 738235ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis skip |= ValidateMemoryIsBoundToBuffer(dev_data, *buffer_state, caller, VALIDATION_ERROR_02544); 738313c4316d0072cbc5bf3cd729abef4d114f3c96edMark Lobodzinski // TODO: If the drawIndirectFirstInstance feature is not enabled, all the firstInstance members of the 738413c4316d0072cbc5bf3cd729abef4d114f3c96edMark Lobodzinski // VkDrawIndirectCommand structures accessed by this command must be 0, which will require access to the contents of 'buffer'. 7385d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis return skip; 7386d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis} 7387d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis 7388ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void PostCallRecordCmdDrawIndirect(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point, 7389ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis BUFFER_STATE *buffer_state) { 7390b68b13ed4952bce61f6ebb0023542660c26b0562Chris Forbes UpdateStateCmdDrawType(dev_data, cb_state, bind_point, CMD_DRAWINDIRECT); 7391d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis AddCommandBufferBindingBuffer(dev_data, cb_state, buffer_state); 7392d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis} 7393d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis 7394bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count, 7395bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski uint32_t stride) { 739656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7397d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis GLOBAL_CB_NODE *cb_state = nullptr; 7398d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis BUFFER_STATE *buffer_state = nullptr; 7399b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7400872a2f0ca3ffdeddfa7483e777191fa64b853892Tony Barbour bool skip = PreCallValidateCmdDrawIndirect(dev_data, commandBuffer, buffer, false, VK_PIPELINE_BIND_POINT_GRAPHICS, &cb_state, 7401ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis &buffer_state, "vkCmdDrawIndirect()"); 7402b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 7403d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis if (!skip) { 74044a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdDrawIndirect(commandBuffer, buffer, offset, count, stride); 7405d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis lock.lock(); 7406ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis PostCallRecordCmdDrawIndirect(dev_data, cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, buffer_state); 7407d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis lock.unlock(); 7408d6df438f6e5bf5142a66c857e5c84dd402451242Tobin Ehlis } 74095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 74105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7411ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool PreCallValidateCmdDrawIndexedIndirect(layer_data *dev_data, VkCommandBuffer cmd_buffer, VkBuffer buffer, bool indexed, 7412ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis VkPipelineBindPoint bind_point, GLOBAL_CB_NODE **cb_state, 7413ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis BUFFER_STATE **buffer_state, const char *caller) { 7414ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis bool skip = ValidateCmdDrawType(dev_data, cmd_buffer, indexed, bind_point, CMD_DRAWINDEXEDINDIRECT, cb_state, caller, 7415baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_01392, VALIDATION_ERROR_01393, VALIDATION_ERROR_02272); 74169a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *buffer_state = GetBufferState(dev_data, buffer); 741735ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis skip |= ValidateMemoryIsBoundToBuffer(dev_data, *buffer_state, caller, VALIDATION_ERROR_02545); 741813c4316d0072cbc5bf3cd729abef4d114f3c96edMark Lobodzinski // TODO: If the drawIndirectFirstInstance feature is not enabled, all the firstInstance members of the 741913c4316d0072cbc5bf3cd729abef4d114f3c96edMark Lobodzinski // VkDrawIndexedIndirectCommand structures accessed by this command must be 0, which will require access to the contents of 742013c4316d0072cbc5bf3cd729abef4d114f3c96edMark Lobodzinski // 'buffer'. 74210c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis return skip; 74220c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis} 74230c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis 7424ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void PostCallRecordCmdDrawIndexedIndirect(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point, 7425ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis BUFFER_STATE *buffer_state) { 7426b68b13ed4952bce61f6ebb0023542660c26b0562Chris Forbes UpdateStateCmdDrawType(dev_data, cb_state, bind_point, CMD_DRAWINDEXEDINDIRECT); 74270c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis AddCommandBufferBindingBuffer(dev_data, cb_state, buffer_state); 74280c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis} 74290c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis 7430bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, 7431bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski uint32_t count, uint32_t stride) { 743256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 74330c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis GLOBAL_CB_NODE *cb_state = nullptr; 74340c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis BUFFER_STATE *buffer_state = nullptr; 7435b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 74360c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis bool skip = PreCallValidateCmdDrawIndexedIndirect(dev_data, commandBuffer, buffer, true, VK_PIPELINE_BIND_POINT_GRAPHICS, 7437ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis &cb_state, &buffer_state, "vkCmdDrawIndexedIndirect()"); 7438b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 74390c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis if (!skip) { 74404a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdDrawIndexedIndirect(commandBuffer, buffer, offset, count, stride); 74410c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis lock.lock(); 7442ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis PostCallRecordCmdDrawIndexedIndirect(dev_data, cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS, buffer_state); 74430c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis lock.unlock(); 74440c9ad626388bcde527db8d89829c45ebf0a94723Tobin Ehlis } 74455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 74465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7447ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool PreCallValidateCmdDispatch(layer_data *dev_data, VkCommandBuffer cmd_buffer, bool indexed, 7448ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis VkPipelineBindPoint bind_point, GLOBAL_CB_NODE **cb_state, const char *caller) { 7449baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt return ValidateCmdDrawType(dev_data, cmd_buffer, indexed, bind_point, CMD_DISPATCH, cb_state, caller, VK_QUEUE_COMPUTE_BIT, 7450baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt VALIDATION_ERROR_01561, VALIDATION_ERROR_01562, VALIDATION_ERROR_UNDEFINED); 745125d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis} 745225d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis 7453ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void PostCallRecordCmdDispatch(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point) { 7454ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis UpdateStateCmdDrawDispatchType(dev_data, cb_state, bind_point, CMD_DISPATCH); 745525d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis} 745625d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis 745789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z) { 745856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 745925d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis GLOBAL_CB_NODE *cb_state = nullptr; 7460b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7461ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis bool skip = 7462ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis PreCallValidateCmdDispatch(dev_data, commandBuffer, false, VK_PIPELINE_BIND_POINT_COMPUTE, &cb_state, "vkCmdDispatch()"); 7463b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 746425d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis if (!skip) { 74654a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdDispatch(commandBuffer, x, y, z); 746625d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis lock.lock(); 7467ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis PostCallRecordCmdDispatch(dev_data, cb_state, VK_PIPELINE_BIND_POINT_COMPUTE); 746825d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis lock.unlock(); 746925d3241067a529052f120867aa4c6161047cdb60Tobin Ehlis } 74705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 74715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7472ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic bool PreCallValidateCmdDispatchIndirect(layer_data *dev_data, VkCommandBuffer cmd_buffer, VkBuffer buffer, bool indexed, 7473ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis VkPipelineBindPoint bind_point, GLOBAL_CB_NODE **cb_state, 7474ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis BUFFER_STATE **buffer_state, const char *caller) { 7475baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt bool skip = 7476baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt ValidateCmdDrawType(dev_data, cmd_buffer, indexed, bind_point, CMD_DISPATCHINDIRECT, cb_state, caller, VK_QUEUE_COMPUTE_BIT, 7477baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt VALIDATION_ERROR_01568, VALIDATION_ERROR_01569, VALIDATION_ERROR_UNDEFINED); 74789a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis *buffer_state = GetBufferState(dev_data, buffer); 747935ec5e14e463d342b74ffe33ee542be13d5c6639Tobin Ehlis skip |= ValidateMemoryIsBoundToBuffer(dev_data, *buffer_state, caller, VALIDATION_ERROR_02547); 748079c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis return skip; 748179c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis} 748279c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis 7483ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlisstatic void PostCallRecordCmdDispatchIndirect(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point, 7484ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis BUFFER_STATE *buffer_state) { 7485ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis UpdateStateCmdDrawDispatchType(dev_data, cb_state, bind_point, CMD_DISPATCHINDIRECT); 748679c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis AddCommandBufferBindingBuffer(dev_data, cb_state, buffer_state); 748779c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis} 748879c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis 7489bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset) { 749056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 749179c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis GLOBAL_CB_NODE *cb_state = nullptr; 749279c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis BUFFER_STATE *buffer_state = nullptr; 7493b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 74947433ab60c7ff16d37edb0f8b17b606ccd363e210Tobin Ehlis bool skip = PreCallValidateCmdDispatchIndirect(dev_data, commandBuffer, buffer, false, VK_PIPELINE_BIND_POINT_COMPUTE, 7495ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis &cb_state, &buffer_state, "vkCmdDispatchIndirect()"); 7496b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 749779c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis if (!skip) { 74984a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdDispatchIndirect(commandBuffer, buffer, offset); 749979c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis lock.lock(); 7500ffa1c08650c9dbe798f25b88bef4b28d33d57b01Tobin Ehlis PostCallRecordCmdDispatchIndirect(dev_data, cb_state, VK_PIPELINE_BIND_POINT_COMPUTE, buffer_state); 750179c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis lock.unlock(); 750279c66dcd1e0db7de8556bce6deb782a150c77b92Tobin Ehlis } 75035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 75045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 750589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdCopyBuffer(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer, 750689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu uint32_t regionCount, const VkBufferCopy *pRegions) { 7507c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7508b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7509ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis 7510c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski auto cb_node = GetCBNode(device_data, commandBuffer); 7511c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski auto src_buffer_state = GetBufferState(device_data, srcBuffer); 7512c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski auto dst_buffer_state = GetBufferState(device_data, dstBuffer); 7513593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 7514c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski if (cb_node && src_buffer_state && dst_buffer_state) { 7515c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski bool skip = PreCallValidateCmdCopyBuffer(device_data, cb_node, src_buffer_state, dst_buffer_state); 7516c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski if (!skip) { 7517c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski PreCallRecordCmdCopyBuffer(device_data, cb_node, src_buffer_state, dst_buffer_state); 7518c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski lock.unlock(); 7519c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski device_data->dispatch_table.CmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, regionCount, pRegions); 7520c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski } 7521ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } else { 7522c40a396f8341e1e1e5fdf1d023a987b874763446Mark Lobodzinski lock.unlock(); 7523ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis assert(0); 75245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 75255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 75265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7527bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdCopyImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, 7528bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, 7529bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkImageCopy *pRegions) { 75306a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski bool skip = false; 75316a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7532b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7533249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis 75346a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski auto cb_node = GetCBNode(device_data, commandBuffer); 75356a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski auto src_image_state = GetImageState(device_data, srcImage); 75366a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski auto dst_image_state = GetImageState(device_data, dstImage); 75371facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis if (cb_node && src_image_state && dst_image_state) { 75386a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski skip = PreCallValidateCmdCopyImage(device_data, cb_node, src_image_state, dst_image_state, regionCount, pRegions, 75396a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski srcImageLayout, dstImageLayout); 75406a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski if (!skip) { 7541a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis PreCallRecordCmdCopyImage(device_data, cb_node, src_image_state, dst_image_state, regionCount, pRegions, srcImageLayout, 7542a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis dstImageLayout); 75436a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski lock.unlock(); 75446a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski device_data->dispatch_table.CmdCopyImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, 75456a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski pRegions); 75465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7547249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis } else { 75486a7544432041a5ced84128597a44c55dfde2105cMark Lobodzinski lock.unlock(); 7549249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis assert(0); 75505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 75515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 75525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7553eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski// Validate that an image's sampleCount matches the requirement for a specific API call 755460568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinskibool ValidateImageSampleCount(layer_data *dev_data, IMAGE_STATE *image_state, VkSampleCountFlagBits sample_count, 755560568995aca225f81acda8ce40cfabbea2c19397Mark Lobodzinski const char *location, UNIQUE_VALIDATION_ERROR_CODE msgCode) { 7556eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski bool skip = false; 75571facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis if (image_state->createInfo.samples != sample_count) { 755855eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen skip = 755955eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 756055eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen reinterpret_cast<uint64_t &>(image_state->image), 0, msgCode, "DS", 756155eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen "%s for image 0x%" PRIxLEAST64 " was created with a sample count of %s but must be %s. %s", location, 756255eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen reinterpret_cast<uint64_t &>(image_state->image), string_VkSampleCountFlagBits(image_state->createInfo.samples), 756355eb01e5950bcb079893cbeee2b487d7e16a79e2Mike Weiblen string_VkSampleCountFlagBits(sample_count), validation_error_map[msgCode]); 7564eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski } 7565eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski return skip; 7566eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski} 7567eebf670a2f04c402f2875f85aa4f889b06db48fcMark Lobodzinski 7568bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBlitImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, 7569bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, 7570bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkImageBlit *pRegions, VkFilter filter) { 757156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7572b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7573593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 75749a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, commandBuffer); 75759a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto src_image_state = GetImageState(dev_data, srcImage); 75769a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto dst_image_state = GetImageState(dev_data, dstImage); 75770dc51740dbd7b9f0ba7c071e0bf96f63d6d48c85Mark Lobodzinski 7578055112ec99304db71d55b69a60e1da14e8af8f60Mark Lobodzinski bool skip = PreCallValidateCmdBlitImage(dev_data, cb_node, src_image_state, dst_image_state, regionCount, pRegions, filter); 75790dc51740dbd7b9f0ba7c071e0bf96f63d6d48c85Mark Lobodzinski 7580dca02371c9531e7a9a2a51decae1db4d297862c4Mark Lobodzinski if (!skip) { 7581eebd811afd800663f15fda8fc71bc203a03fe294Mark Lobodzinski PreCallRecordCmdBlitImage(dev_data, cb_node, src_image_state, dst_image_state); 7582eebd811afd800663f15fda8fc71bc203a03fe294Mark Lobodzinski lock.unlock(); 75834a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdBlitImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, 75844a0754042cf090e131e9e769d8a3633c228625beChris Forbes pRegions, filter); 75850dc51740dbd7b9f0ba7c071e0bf96f63d6d48c85Mark Lobodzinski } 75865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 75875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7588bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdCopyBufferToImage(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage, 7589bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkImageLayout dstImageLayout, uint32_t regionCount, 7590bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkBufferImageCopy *pRegions) { 7591940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7592b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7593940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski bool skip = false; 7594940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski auto cb_node = GetCBNode(device_data, commandBuffer); 7595940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski auto src_buffer_state = GetBufferState(device_data, srcBuffer); 7596940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski auto dst_image_state = GetImageState(device_data, dstImage); 7597940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski if (cb_node && src_buffer_state && dst_image_state) { 7598940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski skip = PreCallValidateCmdCopyBufferToImage(device_data, dstImageLayout, cb_node, src_buffer_state, dst_image_state, 759971c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski regionCount, pRegions, "vkCmdCopyBufferToImage()"); 7600ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } else { 7601d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski lock.unlock(); 7602ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis assert(0); 7603e4d82c37d6c861b388dbc80297c18d6255858cb4Dave Houlton // TODO: report VU01244 here, or put in object tracker? 76045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7605940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski if (!skip) { 7606a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis PreCallRecordCmdCopyBufferToImage(device_data, cb_node, src_buffer_state, dst_image_state, regionCount, pRegions, 7607a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis dstImageLayout); 7608d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski lock.unlock(); 7609940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski device_data->dispatch_table.CmdCopyBufferToImage(commandBuffer, srcBuffer, dstImage, dstImageLayout, regionCount, pRegions); 7610d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski } 76115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 76125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7613bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdCopyImageToBuffer(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, 7614bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkBuffer dstBuffer, uint32_t regionCount, const VkBufferImageCopy *pRegions) { 7615940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski bool skip = false; 7616940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7617b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7618593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 7619940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski auto cb_node = GetCBNode(device_data, commandBuffer); 7620940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski auto src_image_state = GetImageState(device_data, srcImage); 7621940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski auto dst_buffer_state = GetBufferState(device_data, dstBuffer); 7622940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski if (cb_node && src_image_state && dst_buffer_state) { 7623940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski skip = PreCallValidateCmdCopyImageToBuffer(device_data, srcImageLayout, cb_node, src_image_state, dst_buffer_state, 762471c68ce753146a69508694cfc5fc2dcfa08c692eMark Lobodzinski regionCount, pRegions, "vkCmdCopyImageToBuffer()"); 7625ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } else { 7626d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski lock.unlock(); 7627ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis assert(0); 7628e4d82c37d6c861b388dbc80297c18d6255858cb4Dave Houlton // TODO: report VU01262 here, or put in object tracker? 76295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7630940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski if (!skip) { 7631a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis PreCallRecordCmdCopyImageToBuffer(device_data, cb_node, src_image_state, dst_buffer_state, regionCount, pRegions, 7632a07ae8bd5f566eb9b073498dd4280efdb0b838b9Tobin Ehlis srcImageLayout); 7633d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski lock.unlock(); 7634940f70f1340803d185c67633b05ef048d277952eMark Lobodzinski device_data->dispatch_table.CmdCopyImageToBuffer(commandBuffer, srcImage, srcImageLayout, dstBuffer, regionCount, pRegions); 7635d5cde34b61eb694c6fe1d5e53de61bb87bf6936aMark Lobodzinski } 76365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 76375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7638bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdUpdateBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, 7639bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDeviceSize dataSize, const uint32_t *pData) { 76403251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 764156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7642b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7643593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 76449a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, commandBuffer); 76459a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto dst_buff_state = GetBufferState(dev_data, dstBuffer); 76465cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis if (cb_node && dst_buff_state) { 76473251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateMemoryIsBoundToBuffer(dev_data, dst_buff_state, "vkCmdUpdateBuffer()", VALIDATION_ERROR_02530); 7648ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis // Update bindings between buffer and cmd buffer 76495cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis AddCommandBufferBindingBuffer(dev_data, cb_node, dst_buff_state); 7650ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis // Validate that DST buffer has correct usage flags set 76513251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateBufferUsageFlags(dev_data, dst_buff_state, VK_BUFFER_USAGE_TRANSFER_DST_BIT, true, VALIDATION_ERROR_01146, 76523251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkCmdUpdateBuffer()", "VK_BUFFER_USAGE_TRANSFER_DST_BIT"); 7653e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves std::function<bool()> function = [=]() { 76545cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis SetBufferMemoryValid(dev_data, dst_buff_state, true); 7655e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves return false; 76565b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis }; 76579f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis cb_node->validate_functions.push_back(function); 7658593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 76593251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmdQueueFlags(dev_data, cb_node, "vkCmdUpdateBuffer()", 76603251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski VK_QUEUE_TRANSFER_BIT | VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, VALIDATION_ERROR_01154); 76613251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmd(dev_data, cb_node, CMD_UPDATEBUFFER, "vkCmdUpdateBuffer()"); 76621ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(cb_node, CMD_UPDATEBUFFER); 76633251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= insideRenderPass(dev_data, cb_node, "vkCmdUpdateBuffer()", VALIDATION_ERROR_01155); 7664ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } else { 7665ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis assert(0); 76665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7667b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 76683251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdUpdateBuffer(commandBuffer, dstBuffer, dstOffset, dataSize, pData); 76695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 76705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7671bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdFillBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, 7672bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDeviceSize size, uint32_t data) { 767323bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7674b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 767523bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski auto cb_node = GetCBNode(device_data, commandBuffer); 767623bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski auto buffer_state = GetBufferState(device_data, dstBuffer); 7677593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 767823bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski if (cb_node && buffer_state) { 767923bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski bool skip = PreCallValidateCmdFillBuffer(device_data, cb_node, buffer_state); 768023bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski if (!skip) { 768123bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski PreCallRecordCmdFillBuffer(device_data, cb_node, buffer_state); 768223bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski lock.unlock(); 768323bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski device_data->dispatch_table.CmdFillBuffer(commandBuffer, dstBuffer, dstOffset, size, data); 768423bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski } 7685ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } else { 768623bb5a2fd221f6788daf2dd976bf19a5e9b20fb9Mark Lobodzinski lock.unlock(); 7687ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis assert(0); 76885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 76895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 76905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 76914028af23e688ab5730f48ab2244dd042e2eefaedMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdClearAttachments(VkCommandBuffer commandBuffer, uint32_t attachmentCount, 76924028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski const VkClearAttachment *pAttachments, uint32_t rectCount, 76934028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski const VkClearRect *pRects) { 76944028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski bool skip = false; 769556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 76964028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski { 76974028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski std::lock_guard<std::mutex> lock(global_lock); 76984028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski skip = PreCallValidateCmdClearAttachments(dev_data, commandBuffer, attachmentCount, pAttachments, rectCount, pRects); 76994028af23e688ab5730f48ab2244dd042e2eefaedMark Lobodzinski } 7700cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdClearAttachments(commandBuffer, attachmentCount, pAttachments, rectCount, pRects); 77015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 77025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 77030482c55760707900fcd072f6895c121bcf055f6eMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdClearColorImage(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, 77040482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski const VkClearColorValue *pColor, uint32_t rangeCount, 77050482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski const VkImageSubresourceRange *pRanges) { 770656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7707b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 77080482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski 77090482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski bool skip = PreCallValidateCmdClearColorImage(dev_data, commandBuffer, image, imageLayout, rangeCount, pRanges); 77100482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski if (!skip) { 77110482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski PreCallRecordCmdClearImage(dev_data, commandBuffer, image, imageLayout, rangeCount, pRanges, CMD_CLEARCOLORIMAGE); 77120482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski lock.unlock(); 77130482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski dev_data->dispatch_table.CmdClearColorImage(commandBuffer, image, imageLayout, pColor, rangeCount, pRanges); 77140482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski } 77150482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski} 77160482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski 77170482c55760707900fcd072f6895c121bcf055f6eMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdClearDepthStencilImage(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, 77180482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski const VkClearDepthStencilValue *pDepthStencil, uint32_t rangeCount, 77190482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski const VkImageSubresourceRange *pRanges) { 772056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 77210482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski std::unique_lock<std::mutex> lock(global_lock); 77220482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski 77230482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski bool skip = PreCallValidateCmdClearDepthStencilImage(dev_data, commandBuffer, image, imageLayout, rangeCount, pRanges); 77240482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski if (!skip) { 77250482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski PreCallRecordCmdClearImage(dev_data, commandBuffer, image, imageLayout, rangeCount, pRanges, CMD_CLEARDEPTHSTENCILIMAGE); 77260482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski lock.unlock(); 77270482c55760707900fcd072f6895c121bcf055f6eMark Lobodzinski dev_data->dispatch_table.CmdClearDepthStencilImage(commandBuffer, image, imageLayout, pDepthStencil, rangeCount, pRanges); 77287f8aa8f5abceedbb599ef69af1dfbb38c0df2660Slawomir Cygan } 77295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 77305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7731bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdResolveImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, 7732bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, 7733bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkImageResolve *pRegions) { 773456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7735b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 7736593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis 77379a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, commandBuffer); 77389a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto src_image_state = GetImageState(dev_data, srcImage); 77399a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto dst_image_state = GetImageState(dev_data, dstImage); 774009fe5ac5edaec7f0dbcc9fd696e68194569aea89Mark Lobodzinski 774125f7873c9ce3ed39d18bba8750d7538905e150dfMark Lobodzinski bool skip = PreCallValidateCmdResolveImage(dev_data, cb_node, src_image_state, dst_image_state, regionCount, pRegions); 774209fe5ac5edaec7f0dbcc9fd696e68194569aea89Mark Lobodzinski 774309fe5ac5edaec7f0dbcc9fd696e68194569aea89Mark Lobodzinski if (!skip) { 77446c0400e625554ce7fddb833eeace0de19cfcc965Mark Lobodzinski PreCallRecordCmdResolveImage(dev_data, cb_node, src_image_state, dst_image_state); 77456c0400e625554ce7fddb833eeace0de19cfcc965Mark Lobodzinski lock.unlock(); 77464a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdResolveImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, 77474a0754042cf090e131e9e769d8a3633c228625beChris Forbes pRegions); 774809fe5ac5edaec7f0dbcc9fd696e68194569aea89Mark Lobodzinski } 77495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 77505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7751a8d1e377bdeaf61a3209cb997502da4356a185bbMike WeiblenVKAPI_ATTR void VKAPI_CALL GetImageSubresourceLayout(VkDevice device, VkImage image, const VkImageSubresource *pSubresource, 7752a8d1e377bdeaf61a3209cb997502da4356a185bbMike Weiblen VkSubresourceLayout *pLayout) { 7753a8d1e377bdeaf61a3209cb997502da4356a185bbMike Weiblen layer_data *device_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 7754a8d1e377bdeaf61a3209cb997502da4356a185bbMike Weiblen 7755a8d1e377bdeaf61a3209cb997502da4356a185bbMike Weiblen bool skip = PreCallValidateGetImageSubresourceLayout(device_data, image, pSubresource); 7756a8d1e377bdeaf61a3209cb997502da4356a185bbMike Weiblen if (!skip) { 7757b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski device_data->dispatch_table.GetImageSubresourceLayout(device, image, pSubresource, pLayout); 7758b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski } 7759b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski} 7760b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski 7761b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentinebool setEventStageMask(VkQueue queue, VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) { 776256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 77639a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 7764b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine if (pCB) { 7765b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine pCB->eventToStageMap[event] = stageMask; 7766b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine } 7767b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine auto queue_data = dev_data->queueMap.find(queue); 7768b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine if (queue_data != dev_data->queueMap.end()) { 7769b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine queue_data->second.eventToStageMap[event] = stageMask; 7770b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine } 7771b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine return false; 7772b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine} 7773b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine 7774bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdSetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) { 77753251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 777656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7777b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 77789a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 77795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 77803251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdSetEvent()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, 77813251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski VALIDATION_ERROR_00237); 77823251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmd(dev_data, pCB, CMD_SETEVENT, "vkCmdSetEvent()"); 77831ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_SETEVENT); 77843251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= insideRenderPass(dev_data, pCB, "vkCmdSetEvent()", VALIDATION_ERROR_00238); 77853251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 7786208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis ValidateStageMaskGsTsEnables(dev_data, stageMask, "vkCmdSetEvent()", VALIDATION_ERROR_00230, VALIDATION_ERROR_00231); 77879a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto event_state = GetEventNode(dev_data, event); 77884710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis if (event_state) { 77894710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis addCommandBufferBinding(&event_state->cb_bindings, 77907a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski {reinterpret_cast<uint64_t &>(event), kVulkanObjectTypeEvent}, pCB); 77914710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis event_state->cb_bindings.insert(pCB); 7792ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis } 77935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->events.push_back(event); 7794c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine if (!pCB->waitedEvents.count(event)) { 7795c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine pCB->writeEventsBeforeWait.push_back(event); 7796c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine } 7797b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine std::function<bool(VkQueue)> eventUpdate = 7798b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine std::bind(setEventStageMask, std::placeholders::_1, commandBuffer, event, stageMask); 7799b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine pCB->eventUpdates.push_back(eventUpdate); 78005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7801b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 78023251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdSetEvent(commandBuffer, event, stageMask); 78035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 78045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7805bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdResetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) { 78063251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 780756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 7808b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 78099a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 78105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 78113251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdResetEvent()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, 78123251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski VALIDATION_ERROR_00248); 78133251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmd(dev_data, pCB, CMD_RESETEVENT, "vkCmdResetEvent()"); 78141ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_RESETEVENT); 78153251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= insideRenderPass(dev_data, pCB, "vkCmdResetEvent()", VALIDATION_ERROR_00249); 78163251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 7817208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis ValidateStageMaskGsTsEnables(dev_data, stageMask, "vkCmdResetEvent()", VALIDATION_ERROR_00240, VALIDATION_ERROR_00241); 78189a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto event_state = GetEventNode(dev_data, event); 78194710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis if (event_state) { 78204710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis addCommandBufferBinding(&event_state->cb_bindings, 78217a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski {reinterpret_cast<uint64_t &>(event), kVulkanObjectTypeEvent}, pCB); 78224710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis event_state->cb_bindings.insert(pCB); 7823ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis } 78245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->events.push_back(event); 7825c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine if (!pCB->waitedEvents.count(event)) { 7826c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine pCB->writeEventsBeforeWait.push_back(event); 7827c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine } 7828208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis // TODO : Add check for VALIDATION_ERROR_00226 7829b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine std::function<bool(VkQueue)> eventUpdate = 7830b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine std::bind(setEventStageMask, std::placeholders::_1, commandBuffer, event, VkPipelineStageFlags(0)); 7831b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine pCB->eventUpdates.push_back(eventUpdate); 78325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7833b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 78343251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdResetEvent(commandBuffer, event, stageMask); 78355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 78365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 7837e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool ValidateBarriers(const char *funcName, VkCommandBuffer cmdBuffer, uint32_t memBarrierCount, 7838e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves const VkMemoryBarrier *pMemBarriers, uint32_t bufferBarrierCount, 7839e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves const VkBufferMemoryBarrier *pBufferMemBarriers, uint32_t imageMemBarrierCount, 7840e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves const VkImageMemoryBarrier *pImageMemBarriers) { 7841a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis bool skip = false; 784256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(cmdBuffer), layer_data_map); 78439a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, cmdBuffer); 78445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB->activeRenderPass && memBarrierCount) { 7845ee691f5c5fa87aac3750454d2bca2cb582e4e817Chris Forbes if (!pCB->activeRenderPass->hasSelfDependency[pCB->activeSubpass]) { 7846df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 7847df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(cmdBuffer), __LINE__, DRAWSTATE_INVALID_BARRIER, "DS", 7848cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s: Barriers cannot be set during subpass %d " 7849cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "with no self dependency specified.", 7850a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis funcName, pCB->activeSubpass); 78515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 78525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 78535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < imageMemBarrierCount; ++i) { 78545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto mem_barrier = &pImageMemBarriers[i]; 78559a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_data = GetImageState(dev_data, mem_barrier->image); 78566d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis if (image_data) { 78575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t src_q_f_index = mem_barrier->srcQueueFamilyIndex; 78585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t dst_q_f_index = mem_barrier->dstQueueFamilyIndex; 78596d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis if (image_data->createInfo.sharingMode == VK_SHARING_MODE_CONCURRENT) { 78605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // srcQueueFamilyIndex and dstQueueFamilyIndex must both 78615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // be VK_QUEUE_FAMILY_IGNORED 78625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if ((src_q_f_index != VK_QUEUE_FAMILY_IGNORED) || (dst_q_f_index != VK_QUEUE_FAMILY_IGNORED)) { 7863df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 7864df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t>(cmdBuffer), __LINE__, 7865df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski DRAWSTATE_INVALID_QUEUE_INDEX, "DS", 7866df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "%s: Image Barrier for image 0x%" PRIx64 7867df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski " was created with sharingMode of " 7868df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "VK_SHARING_MODE_CONCURRENT. Src and dst " 7869df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "queueFamilyIndices must be VK_QUEUE_FAMILY_IGNORED.", 7870df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski funcName, reinterpret_cast<const uint64_t &>(mem_barrier->image)); 78715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 78725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 78735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Sharing mode is VK_SHARING_MODE_EXCLUSIVE. srcQueueFamilyIndex and 78745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // dstQueueFamilyIndex must either both be VK_QUEUE_FAMILY_IGNORED, 78755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // or both be a valid queue family 78765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (((src_q_f_index == VK_QUEUE_FAMILY_IGNORED) || (dst_q_f_index == VK_QUEUE_FAMILY_IGNORED)) && 78775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (src_q_f_index != dst_q_f_index)) { 7878df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 7879df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t>(cmdBuffer), __LINE__, 7880df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski DRAWSTATE_INVALID_QUEUE_INDEX, "DS", 7881df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "%s: Image 0x%" PRIx64 7882df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski " was created with sharingMode " 7883df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "of VK_SHARING_MODE_EXCLUSIVE. If one of src- or " 7884df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "dstQueueFamilyIndex is VK_QUEUE_FAMILY_IGNORED, both " 7885df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "must be.", 7886df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski funcName, reinterpret_cast<const uint64_t &>(mem_barrier->image)); 78875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (((src_q_f_index != VK_QUEUE_FAMILY_IGNORED) && (dst_q_f_index != VK_QUEUE_FAMILY_IGNORED)) && 7888b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis ((src_q_f_index >= dev_data->phys_dev_properties.queue_family_properties.size()) || 7889b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis (dst_q_f_index >= dev_data->phys_dev_properties.queue_family_properties.size()))) { 7890df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 7891df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t>(cmdBuffer), __LINE__, 7892df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski DRAWSTATE_INVALID_QUEUE_INDEX, "DS", 7893cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s: Image 0x%" PRIx64 7894cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " was created with sharingMode " 7895a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis "of VK_SHARING_MODE_EXCLUSIVE, but srcQueueFamilyIndex %d" 7896a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis " or dstQueueFamilyIndex %d is greater than " PRINTF_SIZE_T_SPECIFIER 7897a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis "queueFamilies crated for this device.", 7898a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis funcName, reinterpret_cast<const uint64_t &>(mem_barrier->image), src_q_f_index, dst_q_f_index, 7899a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis dev_data->phys_dev_properties.queue_family_properties.size()); 79005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 79015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 79025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 79035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 79045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (mem_barrier) { 7905d678ec4f57d80aa89c24562e9ffe941d8d69e455Tony Barbour if (mem_barrier->oldLayout != mem_barrier->newLayout) { 7906a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis skip |= 7907d678ec4f57d80aa89c24562e9ffe941d8d69e455Tony Barbour ValidateMaskBitsFromLayouts(dev_data, cmdBuffer, mem_barrier->srcAccessMask, mem_barrier->oldLayout, "Source"); 7908a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis skip |= 7909d678ec4f57d80aa89c24562e9ffe941d8d69e455Tony Barbour ValidateMaskBitsFromLayouts(dev_data, cmdBuffer, mem_barrier->dstAccessMask, mem_barrier->newLayout, "Dest"); 7910d678ec4f57d80aa89c24562e9ffe941d8d69e455Tony Barbour } 79115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (mem_barrier->newLayout == VK_IMAGE_LAYOUT_UNDEFINED || mem_barrier->newLayout == VK_IMAGE_LAYOUT_PREINITIALIZED) { 7912df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip |= 7913df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 7914df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(cmdBuffer), __LINE__, DRAWSTATE_INVALID_BARRIER, "DS", 7915df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "%s: Image Layout cannot be transitioned to UNDEFINED or " 7916df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "PREINITIALIZED.", 7917df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski funcName); 79185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 79191d5109d5e0dcc530b27e632e73e1be5e12a28dcdJamie Madill VkFormat format = VK_FORMAT_UNDEFINED; 79201d5109d5e0dcc530b27e632e73e1be5e12a28dcdJamie Madill uint32_t arrayLayers = 0, mipLevels = 0; 79215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis bool imageFound = false; 79226d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis if (image_data) { 79236d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis format = image_data->createInfo.format; 79246d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis arrayLayers = image_data->createInfo.arrayLayers; 79256d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis mipLevels = image_data->createInfo.mipLevels; 79265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis imageFound = true; 7927599899dabe438a8ea144c0add628d3f5afe54dd0Chris Forbes } else if (dev_data->device_extensions.khr_swapchain_enabled) { 79289a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto imageswap_data = GetSwapchainFromImage(dev_data, mem_barrier->image); 7929170dc65b45f6bcdec47e02b3aa19435e55b32804Tobin Ehlis if (imageswap_data) { 79309a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto swapchain_data = GetSwapchainNode(dev_data, imageswap_data); 7931b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis if (swapchain_data) { 7932b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis format = swapchain_data->createInfo.imageFormat; 7933b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis arrayLayers = swapchain_data->createInfo.imageArrayLayers; 79345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis mipLevels = 1; 79355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis imageFound = true; 79365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 79375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 79385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 79395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (imageFound) { 7940e08b485346524a30ddfe6526f7dcbbf78c776d10Mark Lobodzinski skip |= ValidateImageSubrangeLevelLayerCounts(dev_data, mem_barrier->subresourceRange, funcName); 7941c37c65e9ff3a0abc86e706ee61d21e1dec882731Tobin Ehlis auto aspect_mask = mem_barrier->subresourceRange.aspectMask; 7942a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis skip |= ValidateImageAspectMask(dev_data, image_data->image, format, aspect_mask, funcName); 794395b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski 794495b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski uint32_t layer_count = ResolveRemainingLayers(&mem_barrier->subresourceRange, image_data->createInfo.arrayLayers); 794595b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski if ((mem_barrier->subresourceRange.baseArrayLayer + layer_count) > arrayLayers) { 7946df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 794795b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t>(cmdBuffer), __LINE__, 794895b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski DRAWSTATE_INVALID_BARRIER, "DS", 794995b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski "%s: Subresource must have the sum of the baseArrayLayer (%d) and layerCount (%d) be less " 7950cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "than or equal to the total number of layers (%d).", 795195b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski funcName, mem_barrier->subresourceRange.baseArrayLayer, layer_count, arrayLayers); 79525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 795395b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski 795495b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski uint32_t level_count = ResolveRemainingLevels(&mem_barrier->subresourceRange, image_data->createInfo.mipLevels); 795595b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski if ((mem_barrier->subresourceRange.baseMipLevel + level_count) > mipLevels) { 7956df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip |= log_msg( 7957df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 7958df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(cmdBuffer), __LINE__, DRAWSTATE_INVALID_BARRIER, "DS", 795995b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski "%s: Subresource must have the sum of the baseMipLevel (%d) and levelCount (%d) be less than or equal to " 7960df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "the total number of levels (%d).", 796195b7894efd5e101e410da92fc697429aec3ffa7bMark Lobodzinski funcName, mem_barrier->subresourceRange.baseMipLevel, level_count, mipLevels); 79625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 79635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 79645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 79655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 79665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < bufferBarrierCount; ++i) { 79675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto mem_barrier = &pBufferMemBarriers[i]; 79685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB->activeRenderPass) { 7969df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 7970df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(cmdBuffer), __LINE__, DRAWSTATE_INVALID_BARRIER, "DS", 7971df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "%s: Buffer Barriers cannot be used during a render pass.", funcName); 79725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 7973cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!mem_barrier) continue; 79745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 79755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Validate buffer barrier queue family indices 79765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if ((mem_barrier->srcQueueFamilyIndex != VK_QUEUE_FAMILY_IGNORED && 7977b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis mem_barrier->srcQueueFamilyIndex >= dev_data->phys_dev_properties.queue_family_properties.size()) || 79785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (mem_barrier->dstQueueFamilyIndex != VK_QUEUE_FAMILY_IGNORED && 7979b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis mem_barrier->dstQueueFamilyIndex >= dev_data->phys_dev_properties.queue_family_properties.size())) { 7980df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 7981df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(cmdBuffer), __LINE__, DRAWSTATE_INVALID_QUEUE_INDEX, "DS", 7982cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "%s: Buffer Barrier 0x%" PRIx64 7983cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " has QueueFamilyIndex greater " 7984a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis "than the number of QueueFamilies (" PRINTF_SIZE_T_SPECIFIER ") for this device.", 7985a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis funcName, reinterpret_cast<const uint64_t &>(mem_barrier->buffer), 7986a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis dev_data->phys_dev_properties.queue_family_properties.size()); 79875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 79885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 79899a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto buffer_state = GetBufferState(dev_data, mem_barrier->buffer); 79905cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis if (buffer_state) { 79915cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis auto buffer_size = buffer_state->requirements.size; 79925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (mem_barrier->offset >= buffer_size) { 7993a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis skip |= log_msg( 7994df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 7995df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(cmdBuffer), __LINE__, DRAWSTATE_INVALID_BARRIER, "DS", 7996df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "%s: Buffer Barrier 0x%" PRIx64 " has offset 0x%" PRIx64 " which is not less than total size 0x%" PRIx64 ".", 799794c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis funcName, reinterpret_cast<const uint64_t &>(mem_barrier->buffer), 7998df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<const uint64_t &>(mem_barrier->offset), reinterpret_cast<const uint64_t &>(buffer_size)); 7999df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski } else if (mem_barrier->size != VK_WHOLE_SIZE && (mem_barrier->offset + mem_barrier->size > buffer_size)) { 8000df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip |= 8001df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 8002df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(cmdBuffer), __LINE__, DRAWSTATE_INVALID_BARRIER, "DS", 8003df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "%s: Buffer Barrier 0x%" PRIx64 " has offset 0x%" PRIx64 " and size 0x%" PRIx64 8004df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski " whose sum is greater than total size 0x%" PRIx64 ".", 8005df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski funcName, reinterpret_cast<const uint64_t &>(mem_barrier->buffer), 8006df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<const uint64_t &>(mem_barrier->offset), 8007df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<const uint64_t &>(mem_barrier->size), reinterpret_cast<const uint64_t &>(buffer_size)); 80085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 80095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 80105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8011a4a1923d21087ded8e990190acd6752264712319Tobin Ehlis return skip; 80125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 80135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8014bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskibool validateEventStageMask(VkQueue queue, GLOBAL_CB_NODE *pCB, uint32_t eventCount, size_t firstEventIndex, 8015bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkPipelineStageFlags sourceStageMask) { 80163251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 8017b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine VkPipelineStageFlags stageMask = 0; 801856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map); 8019b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine for (uint32_t i = 0; i < eventCount; ++i) { 80202ab14387df9b890fe4b13494ea249dd03cf898d2Chris Forbes auto event = pCB->events[firstEventIndex + i]; 8021b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine auto queue_data = dev_data->queueMap.find(queue); 8022cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (queue_data == dev_data->queueMap.end()) return false; 80232ab14387df9b890fe4b13494ea249dd03cf898d2Chris Forbes auto event_data = queue_data->second.eventToStageMap.find(event); 8024b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine if (event_data != queue_data->second.eventToStageMap.end()) { 8025b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine stageMask |= event_data->second; 8026b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine } else { 80279a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto global_event_data = GetEventNode(dev_data, event); 80289556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis if (!global_event_data) { 80293251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT, 80303251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<const uint64_t &>(event), __LINE__, DRAWSTATE_INVALID_EVENT, "DS", 80313251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Event 0x%" PRIx64 " cannot be waited on if it has never been set.", 80323251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<const uint64_t &>(event)); 8033b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine } else { 80349556936067fd0c4eb74c4a13631bc163b154faedTobin Ehlis stageMask |= global_event_data->stageMask; 8035b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine } 8036b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine } 8037b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine } 8038c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine // TODO: Need to validate that host_bit is only set if set event is called 8039c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine // but set event can be called at any time. 8040c1eb2a3736e03aaa15b849d217fd963021dc9780Michael Lentine if (sourceStageMask != stageMask && sourceStageMask != (stageMask | VK_PIPELINE_STAGE_HOST_BIT)) { 80413251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 80423251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t>(pCB->commandBuffer), __LINE__, VALIDATION_ERROR_00254, "DS", 80433251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Submitting cmdbuffer with call to VkCmdWaitEvents " 80443251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "using srcStageMask 0x%X which must be the bitwise " 80453251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "OR of the stageMask parameters used in calls to " 80463251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkCmdSetEvent and VK_PIPELINE_STAGE_HOST_BIT if " 80473251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "used with vkSetEvent but instead is 0x%X. %s", 80483251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski sourceStageMask, stageMask, validation_error_map[VALIDATION_ERROR_00254]); 8049b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine } 80503251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 8051b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine} 8052b4cc521cc1250cec2a064e22a4d840f1ab42370dMichael Lentine 805307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski// Note that we only check bits that HAVE required queueflags -- don't care entries are skipped 805407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinskistatic std::unordered_map<VkPipelineStageFlags, VkQueueFlags> supported_pipeline_stages_table = { 805507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX, VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT}, 805607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT}, 805707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_QUEUE_GRAPHICS_BIT}, 805807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, VK_QUEUE_GRAPHICS_BIT}, 805907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT, VK_QUEUE_GRAPHICS_BIT}, 806007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT, VK_QUEUE_GRAPHICS_BIT}, 806107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT, VK_QUEUE_GRAPHICS_BIT}, 806207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_QUEUE_GRAPHICS_BIT}, 806307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, VK_QUEUE_GRAPHICS_BIT}, 806407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_QUEUE_GRAPHICS_BIT}, 806507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_QUEUE_GRAPHICS_BIT}, 806607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_QUEUE_COMPUTE_BIT}, 806707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_TRANSFER_BIT, VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT}, 806807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski {VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_QUEUE_GRAPHICS_BIT}}; 806907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski 807007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinskistatic const VkPipelineStageFlags stage_flag_bit_array[] = {VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX, 807107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, 807207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 807307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, 807407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT, 807507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT, 807607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT, 807707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 807807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, 807907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, 808007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 808107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 808207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_TRANSFER_BIT, 808307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT}; 808407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski 808507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinskibool CheckStageMaskQueueCompatibility(layer_data *dev_data, VkCommandBuffer command_buffer, VkPipelineStageFlags stage_mask, 808607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VkQueueFlags queue_flags, const char *function, const char *src_or_dest, 808707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski UNIQUE_VALIDATION_ERROR_CODE error_code) { 808807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski bool skip = false; 808907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski // Lookup each bit in the stagemask and check for overlap between its table bits and queue_flags 809007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski for (const auto &item : stage_flag_bit_array) { 809107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski if (stage_mask & item) { 809207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski if ((supported_pipeline_stages_table[item] & queue_flags) == 0) { 809307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski skip |= 809407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 809507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski reinterpret_cast<uint64_t &>(command_buffer), __LINE__, error_code, "DL", 809607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski "%s(): %s flag %s is not compatible with the queue family properties of this " 809707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski "command buffer. %s", 809807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski function, src_or_dest, string_VkPipelineStageFlagBits(static_cast<VkPipelineStageFlagBits>(item)), 809907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski validation_error_map[error_code]); 810007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski } 810107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski } 810207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski } 810307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski return skip; 810407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski} 810507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski 810607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinskibool ValidateStageMasksAgainstQueueCapabilities(layer_data *dev_data, GLOBAL_CB_NODE *cb_state, 810707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VkPipelineStageFlags source_stage_mask, VkPipelineStageFlags dest_stage_mask, 810807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski const char *function, UNIQUE_VALIDATION_ERROR_CODE error_code) { 810907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski bool skip = false; 811007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski uint32_t queue_family_index = dev_data->commandPoolMap[cb_state->createInfo.commandPool].queueFamilyIndex; 811156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(dev_data->physical_device), instance_layer_data_map); 81129a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto physical_device_state = GetPhysicalDeviceState(instance_data, dev_data->physical_device); 811307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski 811407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski // Any pipeline stage included in srcStageMask or dstStageMask must be supported by the capabilities of the queue family 811507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski // specified by the queueFamilyIndex member of the VkCommandPoolCreateInfo structure that was used to create the VkCommandPool 811607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski // that commandBuffer was allocated from, as specified in the table of supported pipeline stages. 811707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski 811807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski if (queue_family_index < physical_device_state->queue_family_properties.size()) { 811907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski VkQueueFlags specified_queue_flags = physical_device_state->queue_family_properties[queue_family_index].queueFlags; 812007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski 812107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski if ((source_stage_mask & VK_PIPELINE_STAGE_ALL_COMMANDS_BIT) == 0) { 812207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski skip |= CheckStageMaskQueueCompatibility(dev_data, cb_state->commandBuffer, source_stage_mask, specified_queue_flags, 812307059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski function, "srcStageMask", error_code); 812407059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski } 812507059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski if ((dest_stage_mask & VK_PIPELINE_STAGE_ALL_COMMANDS_BIT) == 0) { 812607059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski skip |= CheckStageMaskQueueCompatibility(dev_data, cb_state->commandBuffer, dest_stage_mask, specified_queue_flags, 812707059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski function, "dstStageMask", error_code); 812807059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski } 812907059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski } 813007059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski return skip; 813107059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski} 813207059341a6ab09b3bd64727d2689082828492191Mark Lobodzinski 8133d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent *pEvents, 8134d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski VkPipelineStageFlags sourceStageMask, VkPipelineStageFlags dstStageMask, 8135d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers, 8136d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers, 8137d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers) { 8138d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski bool skip = false; 813956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 8140b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 81419a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer); 8142d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski if (cb_state) { 8143d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski skip |= ValidateStageMasksAgainstQueueCapabilities(dev_data, cb_state, sourceStageMask, dstStageMask, "vkCmdWaitEvents", 8144d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski VALIDATION_ERROR_02510); 8145208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis skip |= ValidateStageMaskGsTsEnables(dev_data, sourceStageMask, "vkCmdWaitEvents()", VALIDATION_ERROR_02067, 8146208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis VALIDATION_ERROR_02069); 8147208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis skip |= ValidateStageMaskGsTsEnables(dev_data, dstStageMask, "vkCmdWaitEvents()", VALIDATION_ERROR_02068, 8148208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis VALIDATION_ERROR_02070); 8149d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski auto first_event_index = cb_state->events.size(); 81505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < eventCount; ++i) { 81519a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto event_state = GetEventNode(dev_data, pEvents[i]); 81524710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis if (event_state) { 81534710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis addCommandBufferBinding(&event_state->cb_bindings, 81547a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski {reinterpret_cast<const uint64_t &>(pEvents[i]), kVulkanObjectTypeEvent}, 8155d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski cb_state); 8156d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski event_state->cb_bindings.insert(cb_state); 8157ad13b09db50a49347ea6a8c1408fcc5280042898Tobin Ehlis } 8158d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski cb_state->waitedEvents.insert(pEvents[i]); 8159d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski cb_state->events.push_back(pEvents[i]); 81605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8161d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski std::function<bool(VkQueue)> event_update = 8162d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski std::bind(validateEventStageMask, std::placeholders::_1, cb_state, eventCount, first_event_index, sourceStageMask); 8163d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski cb_state->eventUpdates.push_back(event_update); 8164baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip |= ValidateCmdQueueFlags(dev_data, cb_state, "vkCmdWaitEvents()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, 8165baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt VALIDATION_ERROR_00262); 8166ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski skip |= ValidateCmd(dev_data, cb_state, CMD_WAITEVENTS, "vkCmdWaitEvents()"); 8167ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski UpdateCmdBufferLastCmd(cb_state, CMD_WAITEVENTS); 8168a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen skip |= 8169a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen ValidateBarriersToImages(dev_data, commandBuffer, imageMemoryBarrierCount, pImageMemoryBarriers, "vkCmdWaitEvents()"); 8170e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski if (!skip) { 8171e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski TransitionImageLayouts(dev_data, commandBuffer, imageMemoryBarrierCount, pImageMemoryBarriers); 8172e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski } 8173e659c986db0f3146726d6c744c75772316c3e0c6Mark Lobodzinski 8174364a03b109f0b2b37be2e13d293fa93b8af5203aMike Weiblen skip |= ValidateBarriers("vkCmdWaitEvents()", commandBuffer, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, 8175d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers); 81765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8177b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 8178d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski if (!skip) 81794a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdWaitEvents(commandBuffer, eventCount, pEvents, sourceStageMask, dstStageMask, 81804a0754042cf090e131e9e769d8a3633c228625beChris Forbes memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, 81814a0754042cf090e131e9e769d8a3633c228625beChris Forbes imageMemoryBarrierCount, pImageMemoryBarriers); 81825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 81835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 818403122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinskistatic bool PreCallValidateCmdPipelineBarrier(layer_data *device_data, GLOBAL_CB_NODE *cb_state, VkCommandBuffer commandBuffer, 818503122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, 818603122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers, 818703122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers, 818803122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers) { 818903122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski bool skip = false; 819003122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski skip |= ValidateStageMasksAgainstQueueCapabilities(device_data, cb_state, srcStageMask, dstStageMask, "vkCmdPipelineBarrier", 819103122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski VALIDATION_ERROR_02513); 8192baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip |= ValidateCmdQueueFlags(device_data, cb_state, "vkCmdPipelineBarrier()", 8193baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt VK_QUEUE_TRANSFER_BIT | VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, VALIDATION_ERROR_00280); 819403122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski skip |= ValidateCmd(device_data, cb_state, CMD_PIPELINEBARRIER, "vkCmdPipelineBarrier()"); 819503122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski skip |= ValidateStageMaskGsTsEnables(device_data, srcStageMask, "vkCmdPipelineBarrier()", VALIDATION_ERROR_00265, 819603122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski VALIDATION_ERROR_00267); 819703122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski skip |= ValidateStageMaskGsTsEnables(device_data, dstStageMask, "vkCmdPipelineBarrier()", VALIDATION_ERROR_00266, 819803122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski VALIDATION_ERROR_00268); 8199a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen skip |= ValidateBarriersToImages(device_data, commandBuffer, imageMemoryBarrierCount, pImageMemoryBarriers, 8200a90f5fa414aa0994e67cdb911938e6ae48f2ad6aMike Weiblen "vkCmdPipelineBarrier()"); 820103122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski skip |= ValidateBarriers("vkCmdPipelineBarrier()", commandBuffer, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, 820203122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers); 820303122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski return skip; 820403122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski} 820503122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski 82066f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinskistatic void PreCallRecordCmdPipelineBarrier(layer_data *device_data, GLOBAL_CB_NODE *cb_state, VkCommandBuffer commandBuffer, 82076f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers) { 82086f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski UpdateCmdBufferLastCmd(cb_state, CMD_PIPELINEBARRIER); 82096f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski TransitionImageLayouts(device_data, commandBuffer, imageMemoryBarrierCount, pImageMemoryBarriers); 82106f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski} 82116f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski 8212d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdPipelineBarrier(VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask, 8213d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags, 8214d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers, 8215d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers, 8216d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers) { 8217d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski bool skip = false; 82186f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski layer_data *device_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 8219b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 82206f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski GLOBAL_CB_NODE *cb_state = GetCBNode(device_data, commandBuffer); 8221d91b0b35cff4dc73d88fcf4ea567bd37997bbd98Mark Lobodzinski if (cb_state) { 82226f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski skip |= PreCallValidateCmdPipelineBarrier(device_data, cb_state, commandBuffer, srcStageMask, dstStageMask, 822303122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, 822403122452370ba372b7fb62eaad6ef56a963b3fb0Mark Lobodzinski pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers); 82256f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski if (!skip) { 82266f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski PreCallRecordCmdPipelineBarrier(device_data, cb_state, commandBuffer, imageMemoryBarrierCount, pImageMemoryBarriers); 82276f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski } 82286f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski } else { 82296f88609b0b59259ed29581f1d824ee5e9d7c82ccMark Lobodzinski assert(0); 82305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8231b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 8232a79957f762f6fc6b74c25cb94d35a3fc36967471Tony Barbour if (!skip) { 8233a79957f762f6fc6b74c25cb94d35a3fc36967471Tony Barbour device_data->dispatch_table.CmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, memoryBarrierCount, 8234a79957f762f6fc6b74c25cb94d35a3fc36967471Tony Barbour pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, 8235a79957f762f6fc6b74c25cb94d35a3fc36967471Tony Barbour imageMemoryBarrierCount, pImageMemoryBarriers); 8236a79957f762f6fc6b74c25cb94d35a3fc36967471Tony Barbour } 82375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 82385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8239d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentinebool setQueryState(VkQueue queue, VkCommandBuffer commandBuffer, QueryObject object, bool value) { 824056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 82419a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 8242d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine if (pCB) { 8243d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine pCB->queryToStateMap[object] = value; 8244d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 8245d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine auto queue_data = dev_data->queueMap.find(queue); 8246d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine if (queue_data != dev_data->queueMap.end()) { 8247d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine queue_data->second.queryToStateMap[object] = value; 8248d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 8249d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine return false; 8250d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine} 8251d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine 8252bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBeginQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t slot, VkFlags flags) { 82533251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 825456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 8255b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 82569a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 82575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 82585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis QueryObject query = {queryPool, slot}; 82595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->activeQueries.insert(query); 82605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!pCB->startedQueries.count(query)) { 82615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->startedQueries.insert(query); 82625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 82633251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdBeginQuery()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, 82643251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski VALIDATION_ERROR_01039); 82653251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmd(dev_data, pCB, CMD_BEGINQUERY, "vkCmdBeginQuery()"); 82661ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_BEGINQUERY); 82679a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis addCommandBufferBinding(&GetQueryPoolNode(dev_data, queryPool)->cb_bindings, 82687a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski {reinterpret_cast<uint64_t &>(queryPool), kVulkanObjectTypeQueryPool}, pCB); 82695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8270b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 82713251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdBeginQuery(commandBuffer, queryPool, slot, flags); 82725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 82735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 827489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdEndQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t slot) { 8275946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski bool skip = false; 827656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 8277b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 8278946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer); 8279946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (cb_state) { 82805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis QueryObject query = {queryPool, slot}; 8281946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (!cb_state->activeQueries.count(query)) { 8282df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 8283df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(commandBuffer), __LINE__, VALIDATION_ERROR_01041, "DS", 8284df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "Ending a query before it was started: queryPool 0x%" PRIx64 ", index %d. %s", (uint64_t)(queryPool), 8285df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski slot, validation_error_map[VALIDATION_ERROR_01041]); 82865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 8287946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->activeQueries.erase(query); 82885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8289946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski std::function<bool(VkQueue)> query_update = std::bind(setQueryState, std::placeholders::_1, commandBuffer, query, true); 8290946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->queryUpdates.push_back(query_update); 8291baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip |= ValidateCmdQueueFlags(dev_data, cb_state, "VkCmdEndQuery()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, 8292baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt VALIDATION_ERROR_01046); 8293946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ValidateCmd(dev_data, cb_state, CMD_ENDQUERY, "VkCmdEndQuery()"); 8294946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski UpdateCmdBufferLastCmd(cb_state, CMD_ENDQUERY); 82959a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis addCommandBufferBinding(&GetQueryPoolNode(dev_data, queryPool)->cb_bindings, 82967a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski {reinterpret_cast<uint64_t &>(queryPool), kVulkanObjectTypeQueryPool}, cb_state); 82975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8298b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 8299946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdEndQuery(commandBuffer, queryPool, slot); 83005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 83015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8302bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdResetQueryPool(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, 8303bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski uint32_t queryCount) { 8304946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski bool skip = false; 830556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 8306b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 8307946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer); 8308946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (cb_state) { 83095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < queryCount; i++) { 83105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis QueryObject query = {queryPool, firstQuery + i}; 8311946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->waitedEventsBeforeQueryReset[query] = cb_state->waitedEvents; 8312946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski std::function<bool(VkQueue)> query_update = 8313946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski std::bind(setQueryState, std::placeholders::_1, commandBuffer, query, false); 8314946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->queryUpdates.push_back(query_update); 8315946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski } 8316baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip |= ValidateCmdQueueFlags(dev_data, cb_state, "VkCmdResetQueryPool()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, 8317baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt VALIDATION_ERROR_01024); 8318946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ValidateCmd(dev_data, cb_state, CMD_RESETQUERYPOOL, "VkCmdResetQueryPool()"); 8319946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski UpdateCmdBufferLastCmd(cb_state, CMD_RESETQUERYPOOL); 8320946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= insideRenderPass(dev_data, cb_state, "vkCmdResetQueryPool()", VALIDATION_ERROR_01025); 83219a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis addCommandBufferBinding(&GetQueryPoolNode(dev_data, queryPool)->cb_bindings, 83227a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski {reinterpret_cast<uint64_t &>(queryPool), kVulkanObjectTypeQueryPool}, cb_state); 83235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8324b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 8325946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdResetQueryPool(commandBuffer, queryPool, firstQuery, queryCount); 83265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 83275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8328d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentinebool validateQuery(VkQueue queue, GLOBAL_CB_NODE *pCB, VkQueryPool queryPool, uint32_t queryCount, uint32_t firstQuery) { 83293251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 833056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(pCB->commandBuffer), layer_data_map); 8331d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine auto queue_data = dev_data->queueMap.find(queue); 8332cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (queue_data == dev_data->queueMap.end()) return false; 8333d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine for (uint32_t i = 0; i < queryCount; i++) { 8334d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine QueryObject query = {queryPool, firstQuery + i}; 8335d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine auto query_data = queue_data->second.queryToStateMap.find(query); 8336d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine bool fail = false; 8337d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine if (query_data != queue_data->second.queryToStateMap.end()) { 8338d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine if (!query_data->second) { 8339d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine fail = true; 8340d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 8341d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } else { 8342d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine auto global_query_data = dev_data->queryToStateMap.find(query); 8343d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine if (global_query_data != dev_data->queryToStateMap.end()) { 8344d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine if (!global_query_data->second) { 8345d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine fail = true; 8346d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 8347d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } else { 8348d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine fail = true; 8349d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 8350d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 8351d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine if (fail) { 83523251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 83533251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t>(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_QUERY, "DS", 83543251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Requesting a copy from query to buffer with invalid query: queryPool 0x%" PRIx64 ", index %d", 83553251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t &>(queryPool), firstQuery + i); 8356d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 8357d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine } 83583251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 8359d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine} 8360d78749ee260a3ce7244cbfd97c11aacc2250f8d3Michael Lentine 8361bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdCopyQueryPoolResults(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, 8362bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski uint32_t queryCount, VkBuffer dstBuffer, VkDeviceSize dstOffset, 8363bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDeviceSize stride, VkQueryResultFlags flags) { 8364946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski bool skip = false; 836556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 8366b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 8367ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis 83689a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_node = GetCBNode(dev_data, commandBuffer); 83699a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto dst_buff_state = GetBufferState(dev_data, dstBuffer); 83705cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis if (cb_node && dst_buff_state) { 8371946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ValidateMemoryIsBoundToBuffer(dev_data, dst_buff_state, "vkCmdCopyQueryPoolResults()", VALIDATION_ERROR_02526); 8372ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis // Update bindings between buffer and cmd buffer 83735cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis AddCommandBufferBindingBuffer(dev_data, cb_node, dst_buff_state); 8374ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis // Validate that DST buffer has correct usage flags set 8375946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ValidateBufferUsageFlags(dev_data, dst_buff_state, VK_BUFFER_USAGE_TRANSFER_DST_BIT, true, VALIDATION_ERROR_01066, 8376946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "vkCmdCopyQueryPoolResults()", "VK_BUFFER_USAGE_TRANSFER_DST_BIT"); 8377e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves std::function<bool()> function = [=]() { 83785cca7b0a90e0b6fe1cc28ddbe9037c3ce3f3ee13Tobin Ehlis SetBufferMemoryValid(dev_data, dst_buff_state, true); 8379e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves return false; 83805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis }; 83819f229695cf32913dab3fb75e5d52548ea57b3851Tobin Ehlis cb_node->validate_functions.push_back(function); 8382946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski std::function<bool(VkQueue)> query_update = 8383ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis std::bind(validateQuery, std::placeholders::_1, cb_node, queryPool, queryCount, firstQuery); 8384946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_node->queryUpdates.push_back(query_update); 8385baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip |= ValidateCmdQueueFlags(dev_data, cb_node, "vkCmdCopyQueryPoolResults()", 8386baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, VALIDATION_ERROR_01073); 8387946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ValidateCmd(dev_data, cb_node, CMD_COPYQUERYPOOLRESULTS, "vkCmdCopyQueryPoolResults()"); 8388ecf8b73f862ce67b99fdc57435d3d092afe4e705Mark Lobodzinski UpdateCmdBufferLastCmd(cb_node, CMD_COPYQUERYPOOLRESULTS); 8389946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= insideRenderPass(dev_data, cb_node, "vkCmdCopyQueryPoolResults()", VALIDATION_ERROR_01074); 83909a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis addCommandBufferBinding(&GetQueryPoolNode(dev_data, queryPool)->cb_bindings, 83917a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski {reinterpret_cast<uint64_t &>(queryPool), kVulkanObjectTypeQueryPool}, cb_node); 8392ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis } else { 8393ebc92c86f5a63df6ab4d325f83d385b23c11bf5eTobin Ehlis assert(0); 83945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8395b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 8396946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (!skip) 83974a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdCopyQueryPoolResults(commandBuffer, queryPool, firstQuery, queryCount, dstBuffer, dstOffset, 83984a0754042cf090e131e9e769d8a3633c228625beChris Forbes stride, flags); 83995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 84005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8401bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdPushConstants(VkCommandBuffer commandBuffer, VkPipelineLayout layout, VkShaderStageFlags stageFlags, 8402bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski uint32_t offset, uint32_t size, const void *pValues) { 8403946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski bool skip = false; 840456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 8405b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 8406946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer); 8407946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (cb_state) { 8408baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip |= ValidateCmdQueueFlags(dev_data, cb_state, "vkCmdPushConstants()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, 8409baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt VALIDATION_ERROR_00999); 8410946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ValidateCmd(dev_data, cb_state, CMD_PUSHCONSTANTS, "vkCmdPushConstants()"); 8411946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski UpdateCmdBufferLastCmd(cb_state, CMD_PUSHCONSTANTS); 84125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8413946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= validatePushConstantRange(dev_data, offset, size, "vkCmdPushConstants()"); 84149e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz if (0 == stageFlags) { 8415df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 8416df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(commandBuffer), __LINE__, VALIDATION_ERROR_00996, "DS", 8417df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "vkCmdPushConstants() call has no stageFlags set. %s", validation_error_map[VALIDATION_ERROR_00996]); 84189e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 84199e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz 8420bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz // Check if specified push constant range falls within a pipeline-defined range which has matching stageFlags. 8421bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz // The spec doesn't seem to disallow having multiple push constant ranges with the 8422bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz // same offset and size, but different stageFlags. So we can't just check the 8423bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz // stageFlags in the first range with matching offset and size. 8424bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz if (!skip) { 8425bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz const auto &ranges = getPipelineLayout(dev_data, layout)->push_constant_ranges; 8426bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz bool found_matching_range = false; 8427bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz for (const auto &range : ranges) { 8428bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz if ((stageFlags == range.stageFlags) && (offset >= range.offset) && (offset + size <= range.offset + range.size)) { 8429bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz found_matching_range = true; 843015a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis break; 8431a95cb74c9d0947ab3821b15e1289755286ea78eeKarl Schultz } 84329e24d8153ab63bc3ac08b5a1517c203930b5de91Karl Schultz } 8433bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz if (!found_matching_range) { 8434df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 8435df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(commandBuffer), __LINE__, VALIDATION_ERROR_00988, "DS", 8436df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "vkCmdPushConstants() stageFlags = 0x%" PRIx32 8437df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski " do not match the stageFlags in any of the ranges with" 8438df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski " offset = %d and size = %d in pipeline layout 0x%" PRIx64 ". %s", 8439bf0fa2ad7830118e59f0fb8ff88efae18a72e833Karl Schultz (uint32_t)stageFlags, offset, size, (uint64_t)layout, validation_error_map[VALIDATION_ERROR_00988]); 844015a574466ede280b595c451ad52f2b7b18f20b2dTobin Ehlis } 84415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8442b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 8443946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdPushConstants(commandBuffer, layout, stageFlags, offset, size, pValues); 84445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 84455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8446bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdWriteTimestamp(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, 8447bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkQueryPool queryPool, uint32_t slot) { 8448946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski bool skip = false; 844956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 8450b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 8451946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski GLOBAL_CB_NODE *cb_state = GetCBNode(dev_data, commandBuffer); 8452946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (cb_state) { 84535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis QueryObject query = {queryPool, slot}; 8454946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski std::function<bool(VkQueue)> query_update = std::bind(setQueryState, std::placeholders::_1, commandBuffer, query, true); 8455946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski cb_state->queryUpdates.push_back(query_update); 8456baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt skip |= ValidateCmdQueueFlags(dev_data, cb_state, "vkCmdWriteTimestamp()", VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, 8457baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt VALIDATION_ERROR_01082); 8458946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski skip |= ValidateCmd(dev_data, cb_state, CMD_WRITETIMESTAMP, "vkCmdWriteTimestamp()"); 8459946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski UpdateCmdBufferLastCmd(cb_state, CMD_WRITETIMESTAMP); 84605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8461b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 8462946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdWriteTimestamp(commandBuffer, pipelineStage, queryPool, slot); 84635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 84645b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 84656600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinskistatic bool MatchUsage(layer_data *dev_data, uint32_t count, const VkAttachmentReference *attachments, 84669bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt const VkFramebufferCreateInfo *fbci, VkImageUsageFlagBits usage_flag, 84679bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt UNIQUE_VALIDATION_ERROR_CODE error_code) { 8468946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski bool skip = false; 84696600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski 84706600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski for (uint32_t attach = 0; attach < count; attach++) { 84716600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski if (attachments[attach].attachment != VK_ATTACHMENT_UNUSED) { 84726600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski // Attachment counts are verified elsewhere, but prevent an invalid access 84736600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski if (attachments[attach].attachment < fbci->attachmentCount) { 84746600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski const VkImageView *image_view = &fbci->pAttachments[attachments[attach].attachment]; 84759a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto view_state = GetImageViewState(dev_data, *image_view); 847679fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis if (view_state) { 84779a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis const VkImageCreateInfo *ici = &GetImageState(dev_data, view_state->create_info.image)->createInfo; 84786600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski if (ici != nullptr) { 84796600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski if ((ici->usage & usage_flag) == 0) { 8480df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 8481df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, error_code, "DS", 8482946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "vkCreateFramebuffer: Framebuffer Attachment (%d) conflicts with the image's " 8483946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski "IMAGE_USAGE flags (%s). %s", 8484946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski attachments[attach].attachment, string_VkImageUsageFlagBits(usage_flag), 8485946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski validation_error_map[error_code]); 84866600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski } 84876600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski } 84886600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski } 84896600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski } 84906600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski } 84916600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski } 8492946ddda6ec99e024f51a806278ba21c6779de88aMark Lobodzinski return skip; 84936600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski} 84946600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski 8495d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis// Validate VkFramebufferCreateInfo which includes: 8496d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis// 1. attachmentCount equals renderPass attachmentCount 84975ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 2. corresponding framebuffer and renderpass attachments have matching formats 84985ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 3. corresponding framebuffer and renderpass attachments have matching sample counts 84995ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 4. fb attachments only have a single mip level 85005ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 5. fb attachment dimensions are each at least as large as the fb 85015ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 6. fb attachments use idenity swizzle 85025ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis// 7. fb attachments used by renderPass for color/input/ds have correct usage bit set 85036fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis// 8. fb dimensions are within physical device limits 8504d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlisstatic bool ValidateFramebufferCreateInfo(layer_data *dev_data, const VkFramebufferCreateInfo *pCreateInfo) { 85053251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 85066600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski 85079a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto rp_state = GetRenderPassState(dev_data, pCreateInfo->renderPass); 8508127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis if (rp_state) { 8509127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis const VkRenderPassCreateInfo *rpci = rp_state->createInfo.ptr(); 8510d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis if (rpci->attachmentCount != pCreateInfo->attachmentCount) { 85113251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg( 8512d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT, 85139bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt reinterpret_cast<const uint64_t &>(pCreateInfo->renderPass), __LINE__, VALIDATION_ERROR_00404, "DS", 8514d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis "vkCreateFramebuffer(): VkFramebufferCreateInfo attachmentCount of %u does not match attachmentCount of %u of " 85159bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "renderPass (0x%" PRIxLEAST64 ") being used to create Framebuffer. %s", 85169bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt pCreateInfo->attachmentCount, rpci->attachmentCount, reinterpret_cast<const uint64_t &>(pCreateInfo->renderPass), 85179bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt validation_error_map[VALIDATION_ERROR_00404]); 85185ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis } else { 851941ebcb6b517b1de5ae456d46d866f5e84a96a2c5Tobin Ehlis // attachmentCounts match, so make sure corresponding attachment details line up 85205ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis const VkImageView *image_views = pCreateInfo->pAttachments; 85215ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) { 85229a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto view_state = GetImageViewState(dev_data, image_views[i]); 852312d5600c2f9e32343016fd944432ba95df370797Tobin Ehlis auto &ivci = view_state->create_info; 852479fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis if (ivci.format != rpci->pAttachments[i].format) { 85253251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg( 85265ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT, 85279bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt reinterpret_cast<const uint64_t &>(pCreateInfo->renderPass), __LINE__, VALIDATION_ERROR_00408, "DS", 85289bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "vkCreateFramebuffer(): VkFramebufferCreateInfo attachment #%u has format of %s that does not match " 85299bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "the format of " 85309bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "%s used by the corresponding attachment for renderPass (0x%" PRIxLEAST64 "). %s", 853179fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis i, string_VkFormat(ivci.format), string_VkFormat(rpci->pAttachments[i].format), 85329bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt reinterpret_cast<const uint64_t &>(pCreateInfo->renderPass), validation_error_map[VALIDATION_ERROR_00408]); 85335ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis } 85349a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis const VkImageCreateInfo *ici = &GetImageState(dev_data, ivci.image)->createInfo; 85355ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis if (ici->samples != rpci->pAttachments[i].samples) { 85363251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg( 853741ebcb6b517b1de5ae456d46d866f5e84a96a2c5Tobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT, 85389bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt reinterpret_cast<const uint64_t &>(pCreateInfo->renderPass), __LINE__, VALIDATION_ERROR_00409, "DS", 85399bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "vkCreateFramebuffer(): VkFramebufferCreateInfo attachment #%u has %s samples that do not match " 85409bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "the %s samples used by the corresponding attachment for renderPass (0x%" PRIxLEAST64 "). %s", 854141ebcb6b517b1de5ae456d46d866f5e84a96a2c5Tobin Ehlis i, string_VkSampleCountFlagBits(ici->samples), string_VkSampleCountFlagBits(rpci->pAttachments[i].samples), 85429bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt reinterpret_cast<const uint64_t &>(pCreateInfo->renderPass), validation_error_map[VALIDATION_ERROR_00409]); 85435ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis } 85445ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis // Verify that view only has a single mip level 854579fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis if (ivci.subresourceRange.levelCount != 1) { 85463251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 85473251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski 0, __LINE__, VALIDATION_ERROR_00411, "DS", 85483251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkCreateFramebuffer(): VkFramebufferCreateInfo attachment #%u has mip levelCount of %u " 85493251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "but only a single mip level (levelCount == 1) is allowed when creating a Framebuffer. %s", 85503251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski i, ivci.subresourceRange.levelCount, validation_error_map[VALIDATION_ERROR_00411]); 85515ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis } 855279fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis const uint32_t mip_level = ivci.subresourceRange.baseMipLevel; 8553aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis uint32_t mip_width = max(1u, ici->extent.width >> mip_level); 8554aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis uint32_t mip_height = max(1u, ici->extent.height >> mip_level); 855579fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis if ((ivci.subresourceRange.layerCount < pCreateInfo->layers) || (mip_width < pCreateInfo->width) || 8556aac6fea2aeb81a0d354d80a9226bdc5de2aef5e2Tobin Ehlis (mip_height < pCreateInfo->height)) { 85572c911c34092d685a7fa4630028f6fcf4bf80e349Cort Stratton skip |= log_msg( 85582c911c34092d685a7fa4630028f6fcf4bf80e349Cort Stratton dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 85592c911c34092d685a7fa4630028f6fcf4bf80e349Cort Stratton VALIDATION_ERROR_00410, "DS", 85602c911c34092d685a7fa4630028f6fcf4bf80e349Cort Stratton "vkCreateFramebuffer(): VkFramebufferCreateInfo attachment #%u mip level %u has dimensions smaller " 85612c911c34092d685a7fa4630028f6fcf4bf80e349Cort Stratton "than the corresponding framebuffer dimensions. Here are the respective dimensions for attachment #%u, " 85622c911c34092d685a7fa4630028f6fcf4bf80e349Cort Stratton "framebuffer:\n" 85632c911c34092d685a7fa4630028f6fcf4bf80e349Cort Stratton "width: %u, %u\n" 85642c911c34092d685a7fa4630028f6fcf4bf80e349Cort Stratton "height: %u, %u\n" 85652c911c34092d685a7fa4630028f6fcf4bf80e349Cort Stratton "layerCount: %u, %u\n%s", 85662c911c34092d685a7fa4630028f6fcf4bf80e349Cort Stratton i, ivci.subresourceRange.baseMipLevel, i, mip_width, pCreateInfo->width, mip_height, pCreateInfo->height, 85672c911c34092d685a7fa4630028f6fcf4bf80e349Cort Stratton ivci.subresourceRange.layerCount, pCreateInfo->layers, validation_error_map[VALIDATION_ERROR_00410]); 85685ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis } 856979fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis if (((ivci.components.r != VK_COMPONENT_SWIZZLE_IDENTITY) && (ivci.components.r != VK_COMPONENT_SWIZZLE_R)) || 857079fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis ((ivci.components.g != VK_COMPONENT_SWIZZLE_IDENTITY) && (ivci.components.g != VK_COMPONENT_SWIZZLE_G)) || 857179fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis ((ivci.components.b != VK_COMPONENT_SWIZZLE_IDENTITY) && (ivci.components.b != VK_COMPONENT_SWIZZLE_B)) || 857279fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis ((ivci.components.a != VK_COMPONENT_SWIZZLE_IDENTITY) && (ivci.components.a != VK_COMPONENT_SWIZZLE_A))) { 85733251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg( 85745b9ab1fb8720c30edfbe8dd974e2364425471ad5Mark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 85759bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt VALIDATION_ERROR_00412, "DS", 8576da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis "vkCreateFramebuffer(): VkFramebufferCreateInfo attachment #%u has non-identy swizzle. All framebuffer " 8577da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis "attachments must have been created with the identity swizzle. Here are the actual swizzle values:\n" 8578da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis "r swizzle = %s\n" 8579da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis "g swizzle = %s\n" 8580da5b8b1df2368168be93e563eccdb500d62b97a5Tobin Ehlis "b swizzle = %s\n" 85819bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "a swizzle = %s\n" 85829bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt "%s", 858379fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis i, string_VkComponentSwizzle(ivci.components.r), string_VkComponentSwizzle(ivci.components.g), 85849bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt string_VkComponentSwizzle(ivci.components.b), string_VkComponentSwizzle(ivci.components.a), 85859bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt validation_error_map[VALIDATION_ERROR_00412]); 85865ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis } 85875ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis } 8588d73d9c5ffd42f300d3ec49f64910a2b370694186Tobin Ehlis } 85895ef4ed03801d1456b7c30dd59ea014be126df771Tobin Ehlis // Verify correct attachment usage flags 85906600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski for (uint32_t subpass = 0; subpass < rpci->subpassCount; subpass++) { 85916600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski // Verify input attachments: 85923251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 85939bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt MatchUsage(dev_data, rpci->pSubpasses[subpass].inputAttachmentCount, rpci->pSubpasses[subpass].pInputAttachments, 85949bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt pCreateInfo, VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT, VALIDATION_ERROR_00407); 85956600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski // Verify color attachments: 85963251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 85979bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt MatchUsage(dev_data, rpci->pSubpasses[subpass].colorAttachmentCount, rpci->pSubpasses[subpass].pColorAttachments, 85989bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt pCreateInfo, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VALIDATION_ERROR_00405); 85996600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski // Verify depth/stencil attachments: 86006600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski if (rpci->pSubpasses[subpass].pDepthStencilAttachment != nullptr) { 86013251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= MatchUsage(dev_data, 1, rpci->pSubpasses[subpass].pDepthStencilAttachment, pCreateInfo, 86023251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VALIDATION_ERROR_00406); 86036600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski } 86046600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski } 86056600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski } 86066fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis // Verify FB dimensions are within physical device limits 86079bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt if (pCreateInfo->width > dev_data->phys_dev_properties.properties.limits.maxFramebufferWidth) { 86083251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 86093251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski VALIDATION_ERROR_00413, "DS", 86103251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkCreateFramebuffer(): Requested VkFramebufferCreateInfo width exceeds physical device limits. " 86113251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Requested width: %u, device max: %u\n" 86123251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "%s", 86133251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski pCreateInfo->width, dev_data->phys_dev_properties.properties.limits.maxFramebufferWidth, 86143251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski validation_error_map[VALIDATION_ERROR_00413]); 86159bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt } 86169bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt if (pCreateInfo->height > dev_data->phys_dev_properties.properties.limits.maxFramebufferHeight) { 86173251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 86183251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski VALIDATION_ERROR_00414, "DS", 86193251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkCreateFramebuffer(): Requested VkFramebufferCreateInfo height exceeds physical device limits. " 86203251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Requested height: %u, device max: %u\n" 86213251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "%s", 86223251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski pCreateInfo->height, dev_data->phys_dev_properties.properties.limits.maxFramebufferHeight, 86233251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski validation_error_map[VALIDATION_ERROR_00414]); 86249bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt } 86259bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt if (pCreateInfo->layers > dev_data->phys_dev_properties.properties.limits.maxFramebufferLayers) { 86263251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 86273251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski VALIDATION_ERROR_00415, "DS", 86283251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkCreateFramebuffer(): Requested VkFramebufferCreateInfo layers exceeds physical device limits. " 86293251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Requested layers: %u, device max: %u\n" 86303251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "%s", 86313251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski pCreateInfo->layers, dev_data->phys_dev_properties.properties.limits.maxFramebufferLayers, 86323251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski validation_error_map[VALIDATION_ERROR_00415]); 86336fb721e0f21c85d4457561d17c196280601cebc1Tobin Ehlis } 8634c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton // Verify FB dimensions are greater than zero 8635c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton if (pCreateInfo->width <= 0) { 8636c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 8637c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton VALIDATION_ERROR_02806, "DS", 8638c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton "vkCreateFramebuffer(): Requested VkFramebufferCreateInfo width must be greater than zero. %s", 8639c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton validation_error_map[VALIDATION_ERROR_02806]); 8640c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton } 8641c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton if (pCreateInfo->height <= 0) { 8642c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 8643c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton VALIDATION_ERROR_02807, "DS", 8644c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton "vkCreateFramebuffer(): Requested VkFramebufferCreateInfo height must be greater than zero. %s", 8645c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton validation_error_map[VALIDATION_ERROR_02807]); 8646c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton } 8647c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton if (pCreateInfo->layers <= 0) { 8648c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 8649c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton VALIDATION_ERROR_02808, "DS", 8650c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton "vkCreateFramebuffer(): Requested VkFramebufferCreateInfo layers must be greater than zero. %s", 8651c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton validation_error_map[VALIDATION_ERROR_02808]); 8652c70c914e514d6ee222af18505e6d4ce8387c3fa2Cort Stratton } 86533251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 86546600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski} 86556600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski 865664c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis// Validate VkFramebufferCreateInfo state prior to calling down chain to create Framebuffer object 865764c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis// Return true if an error is encountered and callback returns true to skip call down chain 865864c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis// false indicates that call down chain should proceed 865964c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlisstatic bool PreCallValidateCreateFramebuffer(layer_data *dev_data, const VkFramebufferCreateInfo *pCreateInfo) { 866064c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis // TODO : Verify that renderPass FB is created with is compatible with FB 86613251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 86623251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateFramebufferCreateInfo(dev_data, pCreateInfo); 86633251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 866464c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis} 866564c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis 866654e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis// CreateFramebuffer state has been validated and call down chain completed so record new framebuffer object 866754e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlisstatic void PostCallRecordCreateFramebuffer(layer_data *dev_data, const VkFramebufferCreateInfo *pCreateInfo, VkFramebuffer fb) { 866854e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis // Shadow create info and store in map 8669c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis std::unique_ptr<FRAMEBUFFER_STATE> fb_state( 8670c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis new FRAMEBUFFER_STATE(fb, pCreateInfo, dev_data->renderPassMap[pCreateInfo->renderPass]->createInfo.ptr())); 867176f04ca0e692f9f15d5ef7e0c658c24d11f34ebcTobin Ehlis 867254e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) { 867354e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis VkImageView view = pCreateInfo->pAttachments[i]; 86749a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto view_state = GetImageViewState(dev_data, view); 867579fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis if (!view_state) { 867654e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis continue; 867754e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis } 867854e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis MT_FB_ATTACHMENT_INFO fb_info; 86799a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis fb_info.mem = GetImageState(dev_data, view_state->create_info.image)->binding.mem; 8680883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis fb_info.view_state = view_state; 868179fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis fb_info.image = view_state->create_info.image; 8682c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis fb_state->attachments.push_back(fb_info); 868354e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis } 8684c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis dev_data->frameBufferMap[fb] = std::move(fb_state); 868554e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis} 868654e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis 868789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateFramebuffer(VkDevice device, const VkFramebufferCreateInfo *pCreateInfo, 8688bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkFramebuffer *pFramebuffer) { 868956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 869064c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis std::unique_lock<std::mutex> lock(global_lock); 86913251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = PreCallValidateCreateFramebuffer(dev_data, pCreateInfo); 869264c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis lock.unlock(); 869364c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis 86943251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 869564c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis 86964a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateFramebuffer(device, pCreateInfo, pAllocator, pFramebuffer); 86976600a7662f6dac6a8c8622a8305f02625439bf30Mark Lobodzinski 86985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 869964c259c2660d24b5b032f0cfa668de086dcd7eb4Tobin Ehlis lock.lock(); 870054e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis PostCallRecordCreateFramebuffer(dev_data, pCreateInfo, *pFramebuffer); 870154e0bb0ace13cc34255e0dc9ca6b0da2b4ac5be1Tobin Ehlis lock.unlock(); 87025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 87035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 87045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 87055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 87064e11bb1277f55311686a42000520791e1db1dd7bbungemanstatic bool FindDependency(const uint32_t index, const uint32_t dependent, const std::vector<DAGNode> &subpass_to_node, 8707e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves std::unordered_set<uint32_t> &processed_nodes) { 87085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // If we have already checked this node we have not found a dependency path so return false. 8709cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (processed_nodes.count(index)) return false; 87105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis processed_nodes.insert(index); 87115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const DAGNode &node = subpass_to_node[index]; 87125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Look for a dependency path. If one exists return true else recurse on the previous nodes. 87134e11bb1277f55311686a42000520791e1db1dd7bbungeman if (std::find(node.prev.begin(), node.prev.end(), dependent) == node.prev.end()) { 87145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto elem : node.prev) { 8715cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (FindDependency(elem, dependent, subpass_to_node, processed_nodes)) return true; 87165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 87175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 8718e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves return true; 87195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8720e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves return false; 87215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 87225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 87234e11bb1277f55311686a42000520791e1db1dd7bbungemanstatic bool CheckDependencyExists(const layer_data *dev_data, const uint32_t subpass, 87243251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski const std::vector<uint32_t> &dependent_subpasses, const std::vector<DAGNode> &subpass_to_node, 87253251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool &skip) { 8726e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool result = true; 87275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Loop through all subpasses that share the same attachment and make sure a dependency exists 87285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t k = 0; k < dependent_subpasses.size(); ++k) { 8729cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (static_cast<uint32_t>(subpass) == dependent_subpasses[k]) continue; 87305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const DAGNode &node = subpass_to_node[subpass]; 87315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Check for a specified dependency between the two nodes. If one exists we are done. 87325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto prev_elem = std::find(node.prev.begin(), node.prev.end(), dependent_subpasses[k]); 87335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto next_elem = std::find(node.next.begin(), node.next.end(), dependent_subpasses[k]); 87345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (prev_elem == node.prev.end() && next_elem == node.next.end()) { 87357655cb8b5eb52badee0b011729a05afa36316d69Jan-Harald Fredriksen // If no dependency exits an implicit dependency still might. If not, throw an error. 87365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::unordered_set<uint32_t> processed_nodes; 87377655cb8b5eb52badee0b011729a05afa36316d69Jan-Harald Fredriksen if (!(FindDependency(subpass, dependent_subpasses[k], subpass_to_node, processed_nodes) || 8738bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski FindDependency(dependent_subpasses[k], subpass, subpass_to_node, processed_nodes))) { 87393251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 87403251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS", 87413251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "A dependency between subpasses %d and %d must exist but one is not specified.", subpass, 87423251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski dependent_subpasses[k]); 8743e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves result = false; 87445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 87455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 87465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 87475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 87485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 87495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 87508860b85a52096f9f9b28616bc37feed505497a54Chris Forbesstatic bool CheckPreserved(const layer_data *dev_data, const VkRenderPassCreateInfo *pCreateInfo, const int index, 87513251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski const uint32_t attachment, const std::vector<DAGNode> &subpass_to_node, int depth, bool &skip) { 87525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const DAGNode &node = subpass_to_node[index]; 87535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // If this node writes to the attachment return true as next nodes need to preserve the attachment. 87545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[index]; 87555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) { 8756cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (attachment == subpass.pColorAttachments[j].attachment) return true; 87575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8758a4ea781e8fff70c9db0bedad7fcb6bba08e35da7Tony Barbour for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) { 8759a4ea781e8fff70c9db0bedad7fcb6bba08e35da7Tony Barbour if (attachment == subpass.pInputAttachments[j].attachment) return true; 8760a4ea781e8fff70c9db0bedad7fcb6bba08e35da7Tony Barbour } 87615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) { 8762cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (attachment == subpass.pDepthStencilAttachment->attachment) return true; 87635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8764e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool result = false; 87655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Loop through previous nodes and see if any of them write to the attachment. 87665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto elem : node.prev) { 87673251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski result |= CheckPreserved(dev_data, pCreateInfo, elem, attachment, subpass_to_node, depth + 1, skip); 87685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 87695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // If the attachment was written to by a previous node than this node needs to preserve it. 87705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (result && depth > 0) { 8771e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves bool has_preserved = false; 87725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t j = 0; j < subpass.preserveAttachmentCount; ++j) { 87735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (subpass.pPreserveAttachments[j] == attachment) { 8774e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves has_preserved = true; 87755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis break; 87765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 87775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8778e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves if (!has_preserved) { 87793251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 87803251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS", 87813251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Attachment %d is used by a later subpass and must be preserved in subpass %d.", attachment, index); 87825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 87835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 87845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 87855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 87865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8787cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskitemplate <class T> 8788cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskibool isRangeOverlapping(T offset1, T size1, T offset2, T size2) { 87895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return (((offset1 + size1) > offset2) && ((offset1 + size1) < (offset2 + size2))) || 87905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis ((offset1 > offset2) && (offset1 < (offset2 + size2))); 87915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 87925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 87935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlisbool isRegionOverlapping(VkImageSubresourceRange range1, VkImageSubresourceRange range2) { 87945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return (isRangeOverlapping(range1.baseMipLevel, range1.levelCount, range2.baseMipLevel, range2.levelCount) && 87955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis isRangeOverlapping(range1.baseArrayLayer, range1.layerCount, range2.baseArrayLayer, range2.layerCount)); 87965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 87975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8798c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlisstatic bool ValidateDependencies(const layer_data *dev_data, FRAMEBUFFER_STATE const *framebuffer, 8799127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis RENDER_PASS_STATE const *renderPass) { 88003251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 8801fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes auto const pFramebufferInfo = framebuffer->createInfo.ptr(); 8802fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes auto const pCreateInfo = renderPass->createInfo.ptr(); 8803bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto const &subpass_to_node = renderPass->subpassToNode; 88045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::vector<std::vector<uint32_t>> output_attachment_to_subpass(pCreateInfo->attachmentCount); 88055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::vector<std::vector<uint32_t>> input_attachment_to_subpass(pCreateInfo->attachmentCount); 88065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis std::vector<std::vector<uint32_t>> overlapping_attachments(pCreateInfo->attachmentCount); 88075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Find overlapping attachments 88085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) { 88095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t j = i + 1; j < pCreateInfo->attachmentCount; ++j) { 88105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkImageView viewi = pFramebufferInfo->pAttachments[i]; 88115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkImageView viewj = pFramebufferInfo->pAttachments[j]; 88125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (viewi == viewj) { 88135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis overlapping_attachments[i].push_back(j); 88145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis overlapping_attachments[j].push_back(i); 88155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis continue; 88165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 88179a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto view_state_i = GetImageViewState(dev_data, viewi); 88189a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto view_state_j = GetImageViewState(dev_data, viewj); 881979fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis if (!view_state_i || !view_state_j) { 88205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis continue; 88215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 882279fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis auto view_ci_i = view_state_i->create_info; 882379fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis auto view_ci_j = view_state_j->create_info; 882479fde938178535f598e030a0e9d19a0cb61b72e0Tobin Ehlis if (view_ci_i.image == view_ci_j.image && isRegionOverlapping(view_ci_i.subresourceRange, view_ci_j.subresourceRange)) { 88255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis overlapping_attachments[i].push_back(j); 88265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis overlapping_attachments[j].push_back(i); 88275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis continue; 88285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 88299a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_data_i = GetImageState(dev_data, view_ci_i.image); 88309a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_data_j = GetImageState(dev_data, view_ci_j.image); 88316d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis if (!image_data_i || !image_data_j) { 88325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis continue; 88335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 8834e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis if (image_data_i->binding.mem == image_data_j->binding.mem && 8835e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis isRangeOverlapping(image_data_i->binding.offset, image_data_i->binding.size, image_data_j->binding.offset, 8836e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis image_data_j->binding.size)) { 88375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis overlapping_attachments[i].push_back(j); 88385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis overlapping_attachments[j].push_back(i); 88395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 88405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 88415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 88425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < overlapping_attachments.size(); ++i) { 88435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t attachment = i; 88445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto other_attachment : overlapping_attachments[i]) { 88455b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!(pCreateInfo->pAttachments[attachment].flags & VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT)) { 88463251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 8847df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT, 8848df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<const uint64_t &>(framebuffer->framebuffer), __LINE__, VALIDATION_ERROR_00324, "DS", 8849df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "Attachment %d aliases attachment %d but doesn't " 8850df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "set VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT. %s", 8851df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski attachment, other_attachment, validation_error_map[VALIDATION_ERROR_00324]); 88525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 88535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!(pCreateInfo->pAttachments[other_attachment].flags & VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT)) { 88543251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 8855df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT, 8856df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<const uint64_t &>(framebuffer->framebuffer), __LINE__, VALIDATION_ERROR_00324, "DS", 8857df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "Attachment %d aliases attachment %d but doesn't " 8858df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "set VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT. %s", 8859df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski other_attachment, attachment, validation_error_map[VALIDATION_ERROR_00324]); 88605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 88615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 88625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 88635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Find for each attachment the subpasses that use them. 88641c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young unordered_set<uint32_t> attachmentIndices; 88655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) { 88665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i]; 88671c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young attachmentIndices.clear(); 88685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) { 88695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t attachment = subpass.pInputAttachments[j].attachment; 8870cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (attachment == VK_ATTACHMENT_UNUSED) continue; 88715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis input_attachment_to_subpass[attachment].push_back(i); 88725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto overlapping_attachment : overlapping_attachments[attachment]) { 88735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis input_attachment_to_subpass[overlapping_attachment].push_back(i); 88745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 88755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 88765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) { 88775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t attachment = subpass.pColorAttachments[j].attachment; 8878cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (attachment == VK_ATTACHMENT_UNUSED) continue; 88795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis output_attachment_to_subpass[attachment].push_back(i); 88805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto overlapping_attachment : overlapping_attachments[attachment]) { 88815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis output_attachment_to_subpass[overlapping_attachment].push_back(i); 88825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 88831c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young attachmentIndices.insert(attachment); 88845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 88855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) { 88865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t attachment = subpass.pDepthStencilAttachment->attachment; 88875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis output_attachment_to_subpass[attachment].push_back(i); 88885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto overlapping_attachment : overlapping_attachments[attachment]) { 88895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis output_attachment_to_subpass[overlapping_attachment].push_back(i); 88905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 88911c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young 88921c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young if (attachmentIndices.count(attachment)) { 88933251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 8894df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 8895df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS", 88968860b85a52096f9f9b28616bc37feed505497a54Chris Forbes "Cannot use same attachment (%u) as both color and depth output in same subpass (%u).", attachment, i); 88971c1ee7bf64fb8cc2ba4b8661baa11dce24b3b23aMark Young } 88985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 88995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 89005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // If there is a dependency needed make sure one exists 89015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) { 89025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i]; 89035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // If the attachment is an input then all subpasses that output must have a dependency relationship 89045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) { 890593fe72ec8460857bdb3c101095e6eb96d6171341Chris Forbes uint32_t attachment = subpass.pInputAttachments[j].attachment; 8906cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (attachment == VK_ATTACHMENT_UNUSED) continue; 89073251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski CheckDependencyExists(dev_data, i, output_attachment_to_subpass[attachment], subpass_to_node, skip); 89085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 89095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // If the attachment is an output then all subpasses that use the attachment must have a dependency relationship 89105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) { 891193fe72ec8460857bdb3c101095e6eb96d6171341Chris Forbes uint32_t attachment = subpass.pColorAttachments[j].attachment; 8912cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (attachment == VK_ATTACHMENT_UNUSED) continue; 89133251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski CheckDependencyExists(dev_data, i, output_attachment_to_subpass[attachment], subpass_to_node, skip); 89143251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski CheckDependencyExists(dev_data, i, input_attachment_to_subpass[attachment], subpass_to_node, skip); 89155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 89165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) { 89175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const uint32_t &attachment = subpass.pDepthStencilAttachment->attachment; 89183251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski CheckDependencyExists(dev_data, i, output_attachment_to_subpass[attachment], subpass_to_node, skip); 89193251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski CheckDependencyExists(dev_data, i, input_attachment_to_subpass[attachment], subpass_to_node, skip); 89205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 89215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 89225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Loop through implicit dependencies, if this pass reads make sure the attachment is preserved for all passes after it was 89235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // written. 89245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) { 89255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i]; 89265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) { 89273251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski CheckPreserved(dev_data, pCreateInfo, i, subpass.pInputAttachments[j].attachment, subpass_to_node, 0, skip); 89285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 89295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 89303251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 89315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 89325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 893332f68580aa01aab3e923cb52915a1d3dd4e993c5Chris Forbesstatic bool CreatePassDAG(const layer_data *dev_data, const VkRenderPassCreateInfo *pCreateInfo, 8934e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves std::vector<DAGNode> &subpass_to_node, std::vector<bool> &has_self_dependency) { 89353251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 89365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) { 89375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis DAGNode &subpass_node = subpass_to_node[i]; 89385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis subpass_node.pass = i; 89395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 89405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->dependencyCount; ++i) { 89415b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const VkSubpassDependency &dependency = pCreateInfo->pDependencies[i]; 894266a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes if (dependency.srcSubpass == VK_SUBPASS_EXTERNAL || dependency.dstSubpass == VK_SUBPASS_EXTERNAL) { 894366a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes if (dependency.srcSubpass == dependency.dstSubpass) { 89443251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 8945df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 8946df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS", "The src and dest subpasses cannot both be external."); 894766a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes } 894866a7318a24c9dd8162a6ae49fd62867a263d4402Chris Forbes } else if (dependency.srcSubpass > dependency.dstSubpass) { 89493251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 89503251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS", 89513251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Depedency graph must be specified such that an earlier pass cannot depend on a later pass."); 89525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else if (dependency.srcSubpass == dependency.dstSubpass) { 89535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis has_self_dependency[dependency.srcSubpass] = true; 89545c6aacf95832467d52b2fde1130b04bef559573aChris Forbes } else { 89555c6aacf95832467d52b2fde1130b04bef559573aChris Forbes subpass_to_node[dependency.dstSubpass].prev.push_back(dependency.srcSubpass); 89565c6aacf95832467d52b2fde1130b04bef559573aChris Forbes subpass_to_node[dependency.srcSubpass].next.push_back(dependency.dstSubpass); 89575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 89585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 89593251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 89605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 8961918c283ac4f8c604b79abd0c8b5706d2a7352a34Chris Forbes 896289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo *pCreateInfo, 8963bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkShaderModule *pShaderModule) { 896456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 89653251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 8966c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski spv_result_t spv_valid = SPV_SUCCESS; 8967b1f65702539fd041337fccd493dc6d38dd2a603eChris Forbes 8968e3443707b0f51ba7c6c458c5039dd3004c38b73eMark Lobodzinski if (!GetDisables(dev_data)->shader_validation) { 8969e3443707b0f51ba7c6c458c5039dd3004c38b73eMark Lobodzinski // Use SPIRV-Tools validator to try and catch any issues with the module itself 8970e3443707b0f51ba7c6c458c5039dd3004c38b73eMark Lobodzinski spv_context ctx = spvContextCreate(SPV_ENV_VULKAN_1_0); 8971e3443707b0f51ba7c6c458c5039dd3004c38b73eMark Lobodzinski spv_const_binary_t binary{pCreateInfo->pCode, pCreateInfo->codeSize / sizeof(uint32_t)}; 8972e3443707b0f51ba7c6c458c5039dd3004c38b73eMark Lobodzinski spv_diagnostic diag = nullptr; 8973b1f65702539fd041337fccd493dc6d38dd2a603eChris Forbes 8974c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski spv_valid = spvValidate(ctx, &binary, &diag); 8975c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski if (spv_valid != SPV_SUCCESS) { 89765581a92674a04d2ef49fde417e657f64e3aeed69Mark Lobodzinski if (!dev_data->device_extensions.nv_glsl_shader_enabled || (pCreateInfo->pCode[0] == spv::MagicNumber)) { 89773251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, 89783251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski spv_valid == SPV_WARNING ? VK_DEBUG_REPORT_WARNING_BIT_EXT : VK_DEBUG_REPORT_ERROR_BIT_EXT, 89793251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, SHADER_CHECKER_INCONSISTENT_SPIRV, "SC", 89803251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "SPIR-V module not valid: %s", diag && diag->error ? diag->error : "(no error text)"); 8981c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski } 8982e3443707b0f51ba7c6c458c5039dd3004c38b73eMark Lobodzinski } 89835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8984e3443707b0f51ba7c6c458c5039dd3004c38b73eMark Lobodzinski spvDiagnosticDestroy(diag); 8985e3443707b0f51ba7c6c458c5039dd3004c38b73eMark Lobodzinski spvContextDestroy(ctx); 8986b1f65702539fd041337fccd493dc6d38dd2a603eChris Forbes 89873251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 8988e3443707b0f51ba7c6c458c5039dd3004c38b73eMark Lobodzinski } 89895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 89904a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult res = dev_data->dispatch_table.CreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule); 89915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 8992e3443707b0f51ba7c6c458c5039dd3004c38b73eMark Lobodzinski if (res == VK_SUCCESS && !GetDisables(dev_data)->shader_validation) { 8993b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 8994c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski const auto new_shader_module = (SPV_SUCCESS == spv_valid ? new shader_module(pCreateInfo) : new shader_module()); 8995c73589f3e7b40b57b769dd1e3e9b03e4231b4c69Mark Lobodzinski dev_data->shaderModuleMap[*pShaderModule] = unique_ptr<shader_module>(new_shader_module); 89965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 89975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return res; 89985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 89995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 90004f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinskistatic bool ValidateAttachmentIndex(layer_data *dev_data, uint32_t attachment, uint32_t attachment_count, const char *type) { 90013251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 90024f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski if (attachment >= attachment_count && attachment != VK_ATTACHMENT_UNUSED) { 90033251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 90043251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski VALIDATION_ERROR_00325, "DS", 90053251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "CreateRenderPass: %s attachment %d must be less than the total number of attachments %d. %s", type, 90063251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski attachment, attachment_count, validation_error_map[VALIDATION_ERROR_00325]); 90074f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 90083251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 90094f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski} 90104f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski 9011bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic bool IsPowerOfTwo(unsigned x) { return x && !(x & (x - 1)); } 9012805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes 90134f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinskistatic bool ValidateRenderpassAttachmentUsage(layer_data *dev_data, const VkRenderPassCreateInfo *pCreateInfo) { 90143251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 90154f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) { 90164f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i]; 90174f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski if (subpass.pipelineBindPoint != VK_PIPELINE_BIND_POINT_GRAPHICS) { 90183251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 90193251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski __LINE__, VALIDATION_ERROR_00347, "DS", 90203251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "CreateRenderPass: Pipeline bind point for subpass %d must be VK_PIPELINE_BIND_POINT_GRAPHICS. %s", i, 90213251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski validation_error_map[VALIDATION_ERROR_00347]); 90224f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 90234f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski for (uint32_t j = 0; j < subpass.preserveAttachmentCount; ++j) { 90244f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski uint32_t attachment = subpass.pPreserveAttachments[j]; 90254f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski if (attachment == VK_ATTACHMENT_UNUSED) { 90263251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 90273251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski __LINE__, VALIDATION_ERROR_00356, "DS", 90283251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "CreateRenderPass: Preserve attachment (%d) must not be VK_ATTACHMENT_UNUSED. %s", j, 90293251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski validation_error_map[VALIDATION_ERROR_00356]); 90304f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } else { 90313251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateAttachmentIndex(dev_data, attachment, pCreateInfo->attachmentCount, "Preserve"); 90324f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 90334f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 90346a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes 9035bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto subpass_performs_resolve = 9036bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski subpass.pResolveAttachments && 9037bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski std::any_of(subpass.pResolveAttachments, subpass.pResolveAttachments + subpass.colorAttachmentCount, 9038bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski [](VkAttachmentReference ref) { return ref.attachment != VK_ATTACHMENT_UNUSED; }); 90396a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes 9040805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes unsigned sample_count = 0; 9041805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes 90424f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) { 90434f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski uint32_t attachment; 90444f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski if (subpass.pResolveAttachments) { 90454f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski attachment = subpass.pResolveAttachments[j].attachment; 90463251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateAttachmentIndex(dev_data, attachment, pCreateInfo->attachmentCount, "Resolve"); 90476a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes 90483251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip && attachment != VK_ATTACHMENT_UNUSED && 90496a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes pCreateInfo->pAttachments[attachment].samples != VK_SAMPLE_COUNT_1_BIT) { 90503251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 90513251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski 0, __LINE__, VALIDATION_ERROR_00352, "DS", 90523251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "CreateRenderPass: Subpass %u requests multisample resolve into attachment %u, " 90533251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "which must have VK_SAMPLE_COUNT_1_BIT but has %s. %s", 90543251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski i, attachment, string_VkSampleCountFlagBits(pCreateInfo->pAttachments[attachment].samples), 90553251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski validation_error_map[VALIDATION_ERROR_00352]); 90566a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes } 90574f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 90584f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski attachment = subpass.pColorAttachments[j].attachment; 90593251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateAttachmentIndex(dev_data, attachment, pCreateInfo->attachmentCount, "Color"); 90606a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes 90613251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip && attachment != VK_ATTACHMENT_UNUSED) { 9062805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes sample_count |= (unsigned)pCreateInfo->pAttachments[attachment].samples; 9063805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes 9064bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (subpass_performs_resolve && pCreateInfo->pAttachments[attachment].samples == VK_SAMPLE_COUNT_1_BIT) { 90653251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 90663251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski 0, __LINE__, VALIDATION_ERROR_00351, "DS", 90673251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "CreateRenderPass: Subpass %u requests multisample resolve from attachment %u " 90683251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "which has VK_SAMPLE_COUNT_1_BIT. %s", 90693251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski i, attachment, validation_error_map[VALIDATION_ERROR_00351]); 9070dc7c45f01ae5690f7c969b4760463c1a6bac52d5Chris Forbes } 90716a3bc5f071fe21799f0f7ae844716c333f11f39cChris Forbes } 90724f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 9073dc7c45f01ae5690f7c969b4760463c1a6bac52d5Chris Forbes 90744f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) { 90754f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski uint32_t attachment = subpass.pDepthStencilAttachment->attachment; 90763251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateAttachmentIndex(dev_data, attachment, pCreateInfo->attachmentCount, "Depth stencil"); 9077805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes 90783251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip && attachment != VK_ATTACHMENT_UNUSED) { 9079805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes sample_count |= (unsigned)pCreateInfo->pAttachments[attachment].samples; 9080805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes } 90814f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 9082dc7c45f01ae5690f7c969b4760463c1a6bac52d5Chris Forbes 90834f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) { 90844f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski uint32_t attachment = subpass.pInputAttachments[j].attachment; 90853251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateAttachmentIndex(dev_data, attachment, pCreateInfo->attachmentCount, "Input"); 90864f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 9087805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes 9088805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes if (sample_count && !IsPowerOfTwo(sample_count)) { 90893251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, 90903251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski __LINE__, VALIDATION_ERROR_00337, "DS", 90913251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "CreateRenderPass: Subpass %u attempts to render to " 90923251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "attachments with inconsistent sample counts. %s", 90933251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski i, validation_error_map[VALIDATION_ERROR_00337]); 9094805ec497391f6bc513f7653ba6d535c509b54062Chris Forbes } 90954f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 90963251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 90974f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski} 90984f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski 90995245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbesstatic void MarkAttachmentFirstUse(RENDER_PASS_STATE *render_pass, 91005245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes uint32_t index, 91015245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes bool is_read) { 91025245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes if (index == VK_ATTACHMENT_UNUSED) 91035245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes return; 91045245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes 91055245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes if (!render_pass->attachment_first_read.count(index)) 91065245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes render_pass->attachment_first_read[index] = is_read; 91075245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes} 91085245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes 910989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateRenderPass(VkDevice device, const VkRenderPassCreateInfo *pCreateInfo, 91104f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass) { 91113251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 911256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 91134f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski 91144f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski std::unique_lock<std::mutex> lock(global_lock); 91154f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski // TODO: As part of wrapping up the mem_tracker/core_validation merge the following routine should be consolidated with 91164f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski // ValidateLayouts. 91173251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateRenderpassAttachmentUsage(dev_data, pCreateInfo); 9118208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->dependencyCount; ++i) { 91193251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateStageMaskGsTsEnables(dev_data, pCreateInfo->pDependencies[i].srcStageMask, "vkCreateRenderPass()", 91203251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski VALIDATION_ERROR_00368, VALIDATION_ERROR_00370); 91213251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateStageMaskGsTsEnables(dev_data, pCreateInfo->pDependencies[i].dstStageMask, "vkCreateRenderPass()", 91223251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski VALIDATION_ERROR_00369, VALIDATION_ERROR_00371); 9123208aecf4cb59762be429488d7d4484f138c2cd81Tobin Ehlis } 91243251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) { 91253251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateLayouts(dev_data, device, pCreateInfo); 9126ab38df28c5ae1816c5fa33c0c7840c6950e83f0dChris Forbes } 9127ff6101de02d1677fb54962e2ff57875e76898e26Chris Forbes lock.unlock(); 91284f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski 91293251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (skip) { 91304f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski return VK_ERROR_VALIDATION_FAILED_EXT; 91314f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski } 91324f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski 91334a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateRenderPass(device, pCreateInfo, pAllocator, pRenderPass); 9134ff6101de02d1677fb54962e2ff57875e76898e26Chris Forbes 91355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 91364f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski lock.lock(); 91374f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski 91384f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski std::vector<bool> has_self_dependency(pCreateInfo->subpassCount); 91394f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski std::vector<DAGNode> subpass_to_node(pCreateInfo->subpassCount); 914032f68580aa01aab3e923cb52915a1d3dd4e993c5Chris Forbes skip |= CreatePassDAG(dev_data, pCreateInfo, subpass_to_node, has_self_dependency); 91414f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski 9142127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis auto render_pass = unique_ptr<RENDER_PASS_STATE>(new RENDER_PASS_STATE(pCreateInfo)); 914398cddf7090b5d5dcc382045867753ef703d1c3d3Chris Forbes render_pass->renderPass = *pRenderPass; 9144cf2686cdbb12af8a29ca598c126b5e37215f0ef7Chris Forbes render_pass->hasSelfDependency = has_self_dependency; 9145cf2686cdbb12af8a29ca598c126b5e37215f0ef7Chris Forbes render_pass->subpassToNode = subpass_to_node; 9146db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes 914787e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) { 914887e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i]; 914987e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) { 91505245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes MarkAttachmentFirstUse(render_pass.get(), subpass.pColorAttachments[j].attachment, false); 91519cde292b1c19c643b7c13018d9834cccfe6ef7eaChris Forbes 91525245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes // resolve attachments are considered to be written 91535245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes if (subpass.pResolveAttachments) { 91545245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes MarkAttachmentFirstUse(render_pass.get(), subpass.pResolveAttachments[j].attachment, false); 91559cde292b1c19c643b7c13018d9834cccfe6ef7eaChris Forbes } 915687e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis } 91575245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes if (subpass.pDepthStencilAttachment) { 91585245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes MarkAttachmentFirstUse(render_pass.get(), subpass.pDepthStencilAttachment->attachment, false); 915987e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis } 9160a5ce96d7c88653668a2b33a6b72bd3cb16d73f48Michael Lentine for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) { 91615245a74f239ad662d9ca3675789ad41f37424ce6Chris Forbes MarkAttachmentFirstUse(render_pass.get(), subpass.pInputAttachments[j].attachment, true); 9162a5ce96d7c88653668a2b33a6b72bd3cb16d73f48Michael Lentine } 916387e0afcd98dcf3c1e5e2cbb3023fe89d9dd10cd2Tobin Ehlis } 9164db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes 9165fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes dev_data->renderPassMap[*pRenderPass] = std::move(render_pass); 91665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 91675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 91685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 91694f76794409854faf16dd51f37d5fa21dff1c5d44Mark Lobodzinski 9170eb4c61477130f69f48fdf3ac31cb82104181cc73Chris Forbesstatic bool validatePrimaryCommandBuffer(const layer_data *dev_data, const GLOBAL_CB_NODE *pCB, char const *cmd_name, 91719bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt UNIQUE_VALIDATION_ERROR_CODE error_code) { 91723251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 91735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB->createInfo.level != VK_COMMAND_BUFFER_LEVEL_PRIMARY) { 91743251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 91753251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t>(pCB->commandBuffer), __LINE__, error_code, "DS", 9176eb4c61477130f69f48fdf3ac31cb82104181cc73Chris Forbes "Cannot execute command %s on a secondary command buffer. %s", cmd_name, 91773251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski validation_error_map[error_code]); 91785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 91793251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 91805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 91815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 91828860b85a52096f9f9b28616bc37feed505497a54Chris Forbesstatic bool VerifyRenderAreaBounds(const layer_data *dev_data, const VkRenderPassBeginInfo *pRenderPassBegin) { 91833251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 9184c54e405a4ce05f4de10bb78bfc3a4769c41d2d59Tobin Ehlis const safe_VkFramebufferCreateInfo *pFramebufferInfo = 91859a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis &GetFramebufferState(dev_data, pRenderPassBegin->framebuffer)->createInfo; 9186885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine if (pRenderPassBegin->renderArea.offset.x < 0 || 9187885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine (pRenderPassBegin->renderArea.offset.x + pRenderPassBegin->renderArea.extent.width) > pFramebufferInfo->width || 9188885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine pRenderPassBegin->renderArea.offset.y < 0 || 9189885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine (pRenderPassBegin->renderArea.offset.y + pRenderPassBegin->renderArea.extent.height) > pFramebufferInfo->height) { 91903251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= static_cast<bool>(log_msg( 9191df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 9192885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine DRAWSTATE_INVALID_RENDER_AREA, "CORE", 9193885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine "Cannot execute a render pass with renderArea not within the bound of the " 9194885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine "framebuffer. RenderArea: x %d, y %d, width %d, height %d. Framebuffer: width %d, " 9195885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine "height %d.", 9196885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine pRenderPassBegin->renderArea.offset.x, pRenderPassBegin->renderArea.offset.y, pRenderPassBegin->renderArea.extent.width, 9197885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine pRenderPassBegin->renderArea.extent.height, pFramebufferInfo->width, pFramebufferInfo->height)); 9198885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine } 91993251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 9200885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine} 9201885537d813d6fb3d199e76f6d63b6d3f78d0eeb0Michael Lentine 92021a65650f856376768d7b03ea2d080aaff87cacfdMark 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 92031a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski// [load|store]Op flag must be checked 92041a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski// TODO: The memory valid flag in DEVICE_MEM_INFO should probably be split to track the validity of stencil memory separately. 9205cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskitemplate <typename T> 9206cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinskistatic bool FormatSpecificLoadAndStoreOpSettings(VkFormat format, T color_depth_op, T stencil_op, T op) { 9207a49b8a211ce07e7fa2225d23f8cb11f1055b418aMark Lobodzinski if (color_depth_op != op && stencil_op != op) { 9208a49b8a211ce07e7fa2225d23f8cb11f1055b418aMark Lobodzinski return false; 9209a49b8a211ce07e7fa2225d23f8cb11f1055b418aMark Lobodzinski } 921016769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton bool check_color_depth_load_op = !FormatIsStencilOnly(format); 921116769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton bool check_stencil_load_op = FormatIsDepthAndStencil(format) || !check_color_depth_load_op; 9212a49b8a211ce07e7fa2225d23f8cb11f1055b418aMark Lobodzinski 92130d9453d85335963d6cabfbf400b058dc905ea238Chris Forbes return ((check_color_depth_load_op && (color_depth_op == op)) || 92140d9453d85335963d6cabfbf400b058dc905ea238Chris Forbes (check_stencil_load_op && (stencil_op == op))); 92151a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski} 92161a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski 9217bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdBeginRenderPass(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *pRenderPassBegin, 9218bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkSubpassContents contents) { 92193251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 922056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 9221b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 92229a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *cb_node = GetCBNode(dev_data, commandBuffer); 92239a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto render_pass_state = pRenderPassBegin ? GetRenderPassState(dev_data, pRenderPassBegin->renderPass) : nullptr; 92249a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto framebuffer = pRenderPassBegin ? GetFramebufferState(dev_data, pRenderPassBegin->framebuffer) : nullptr; 9225f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis if (cb_node) { 9226308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski if (render_pass_state) { 9227cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski uint32_t clear_op_size = 0; // Make sure pClearValues is at least as large as last LOAD_OP_CLEAR 9228f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->activeFramebuffer = pRenderPassBegin->framebuffer; 9229308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski for (uint32_t i = 0; i < render_pass_state->createInfo.attachmentCount; ++i) { 9230f40ab6d10b8d755ce0e461c33916b0d4d5a5d437Chris Forbes MT_FB_ATTACHMENT_INFO &fb_info = framebuffer->attachments[i]; 9231308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski auto pAttachment = &render_pass_state->createInfo.pAttachments[i]; 9232bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (FormatSpecificLoadAndStoreOpSettings(pAttachment->format, pAttachment->loadOp, pAttachment->stencilLoadOp, 92331a65650f856376768d7b03ea2d080aaff87cacfdMark Lobodzinski VK_ATTACHMENT_LOAD_OP_CLEAR)) { 923492bc0680357019834b7529148ab6d73353ce02c7Mark Lobodzinski clear_op_size = static_cast<uint32_t>(i) + 1; 923516387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes std::function<bool()> function = [=]() { 92369a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis SetImageMemoryValid(dev_data, GetImageState(dev_data, fb_info.image), true); 923716387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes return false; 923816387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes }; 9239f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->validate_functions.push_back(function); 9240db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes } else if (FormatSpecificLoadAndStoreOpSettings(pAttachment->format, pAttachment->loadOp, 9241bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pAttachment->stencilLoadOp, VK_ATTACHMENT_LOAD_OP_DONT_CARE)) { 924216387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes std::function<bool()> function = [=]() { 92439a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis SetImageMemoryValid(dev_data, GetImageState(dev_data, fb_info.image), false); 924416387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes return false; 924516387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes }; 9246f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->validate_functions.push_back(function); 9247db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes } else if (FormatSpecificLoadAndStoreOpSettings(pAttachment->format, pAttachment->loadOp, 9248bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pAttachment->stencilLoadOp, VK_ATTACHMENT_LOAD_OP_LOAD)) { 924916387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes std::function<bool()> function = [=]() { 92509a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis return ValidateImageMemoryIsValid(dev_data, GetImageState(dev_data, fb_info.image), 9251f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis "vkCmdBeginRenderPass()"); 925216387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes }; 9253f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->validate_functions.push_back(function); 925416387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes } 9255308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski if (render_pass_state->attachment_first_read[i]) { 925616387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes std::function<bool()> function = [=]() { 92579a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis return ValidateImageMemoryIsValid(dev_data, GetImageState(dev_data, fb_info.image), 9258f989de4217bce0f293121d0da53dc8328276370fTobin Ehlis "vkCmdBeginRenderPass()"); 925916387282d11e414ae7cb9ddf3d0c1bebf8f2c74dChris Forbes }; 9260f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->validate_functions.push_back(function); 92615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 92625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 92636de3c6ffa0819ee37cd5cecee918b062145e2ff1Tobin Ehlis if (clear_op_size > pRenderPassBegin->clearValueCount) { 92643251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg( 9265369cf6deef1fca74f9eb1f8ef6e96deba715b133Slawomir Cygan dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT, 9266308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski reinterpret_cast<uint64_t &>(render_pass_state->renderPass), __LINE__, VALIDATION_ERROR_00442, "DS", 9267bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "In vkCmdBeginRenderPass() the VkRenderPassBeginInfo struct has a clearValueCount of %u but there must " 9268bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "be at least %u entries in pClearValues array to account for the highest index attachment in renderPass " 9269cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "0x%" PRIx64 9270cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski " that uses VK_ATTACHMENT_LOAD_OP_CLEAR is %u. Note that the pClearValues array " 9271bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "is indexed by attachment number so even if some pClearValues entries between 0 and %u correspond to " 9272bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "attachments that aren't cleared they will be ignored. %s", 9273308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski pRenderPassBegin->clearValueCount, clear_op_size, reinterpret_cast<uint64_t &>(render_pass_state->renderPass), 92745504d0369cbc97ad7c221eddbad439bfb83e3fb6Mark Lobodzinski clear_op_size, clear_op_size - 1, validation_error_map[VALIDATION_ERROR_00442]); 9275369cf6deef1fca74f9eb1f8ef6e96deba715b133Slawomir Cygan } 9276369cf6deef1fca74f9eb1f8ef6e96deba715b133Slawomir Cygan if (clear_op_size < pRenderPassBegin->clearValueCount) { 92773251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg( 9278369cf6deef1fca74f9eb1f8ef6e96deba715b133Slawomir Cygan dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT, 9279308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski reinterpret_cast<uint64_t &>(render_pass_state->renderPass), __LINE__, 9280308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski DRAWSTATE_RENDERPASS_TOO_MANY_CLEAR_VALUES, "DS", 9281369cf6deef1fca74f9eb1f8ef6e96deba715b133Slawomir Cygan "In vkCmdBeginRenderPass() the VkRenderPassBeginInfo struct has a clearValueCount of %u but only first %u " 92827bab3d8f0599701f6e26a2d76314588486ae99c9Mark Lobodzinski "entries in pClearValues array are used. The highest index of any attachment in renderPass 0x%" PRIx64 9283369cf6deef1fca74f9eb1f8ef6e96deba715b133Slawomir Cygan " that uses VK_ATTACHMENT_LOAD_OP_CLEAR is %u - other pClearValues are ignored.", 9284308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski pRenderPassBegin->clearValueCount, clear_op_size, reinterpret_cast<uint64_t &>(render_pass_state->renderPass), 92857bab3d8f0599701f6e26a2d76314588486ae99c9Mark Lobodzinski clear_op_size - 1); 92863d71bca42a843966040d6ada9c029e0ec9f35ca6Tobin Ehlis } 92873251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= VerifyRenderAreaBounds(dev_data, pRenderPassBegin); 92883251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= VerifyFramebufferAndRenderPassLayouts(dev_data, cb_node, pRenderPassBegin, 92893251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski GetFramebufferState(dev_data, pRenderPassBegin->framebuffer)); 92903251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= insideRenderPass(dev_data, cb_node, "vkCmdBeginRenderPass()", VALIDATION_ERROR_00440); 92913251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateDependencies(dev_data, framebuffer, render_pass_state); 9292eb4c61477130f69f48fdf3ac31cb82104181cc73Chris Forbes skip |= validatePrimaryCommandBuffer(dev_data, cb_node, "vkCmdBeginRenderPass()", VALIDATION_ERROR_00441); 92933251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 9294baa50ccc5a8cf7a6f7474148f301802c5480e715Mike Schuchardt ValidateCmdQueueFlags(dev_data, cb_node, "vkCmdBeginRenderPass()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_00439); 92953251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmd(dev_data, cb_node, CMD_BEGINRENDERPASS, "vkCmdBeginRenderPass()"); 92961ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(cb_node, CMD_BEGINRENDERPASS); 9297308153fd68fc050a302201fb5a7cca53de8dc866Mark Lobodzinski cb_node->activeRenderPass = render_pass_state; 92985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // This is a shallow copy as that is all that is needed for now 9299f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->activeRenderPassBeginInfo = *pRenderPassBegin; 9300f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->activeSubpass = 0; 9301f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->activeSubpassContents = contents; 9302f909505280723ee24d2e74afc759d38dc09a37beTobin Ehlis cb_node->framebuffers.insert(pRenderPassBegin->framebuffer); 9303883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis // Connect this framebuffer and its children to this cmdBuffer 9304883ee3f865f9dbd83134d148b26e96cb6a926b3dTobin Ehlis AddFramebufferBinding(dev_data, cb_node, framebuffer); 93055f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis // transition attachments to the correct layouts for beginning of renderPass and first subpass 93065f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis TransitionBeginRenderPassLayouts(dev_data, cb_node, render_pass_state, framebuffer); 93075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 93085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9309b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 93103251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) { 93114a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdBeginRenderPass(commandBuffer, pRenderPassBegin, contents); 93125b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 93135b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 93145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 931589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents) { 93163251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 931756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 9318b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 93199a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 93205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 9321eb4c61477130f69f48fdf3ac31cb82104181cc73Chris Forbes skip |= validatePrimaryCommandBuffer(dev_data, pCB, "vkCmdNextSubpass()", VALIDATION_ERROR_00459); 93223251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdNextSubpass()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_00457); 93233251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmd(dev_data, pCB, CMD_NEXTSUBPASS, "vkCmdNextSubpass()"); 93241ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_NEXTSUBPASS); 93253251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= outsideRenderPass(dev_data, pCB, "vkCmdNextSubpass()", VALIDATION_ERROR_00458); 932680281691386b37385846f21b38e8c9d4b12cc74eChris Forbes 9327fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes auto subpassCount = pCB->activeRenderPass->createInfo.subpassCount; 932880281691386b37385846f21b38e8c9d4b12cc74eChris Forbes if (pCB->activeSubpass == subpassCount - 1) { 93293251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 93303251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t>(commandBuffer), __LINE__, VALIDATION_ERROR_00453, "DS", 93313251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkCmdNextSubpass(): Attempted to advance beyond final subpass. %s", 93323251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski validation_error_map[VALIDATION_ERROR_00453]); 933380281691386b37385846f21b38e8c9d4b12cc74eChris Forbes } 93345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9335b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 933696ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes 93373251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (skip) return; 933896ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes 93394a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdNextSubpass(commandBuffer, contents); 934096ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes 934196ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes if (pCB) { 9342bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski lock.lock(); 9343bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pCB->activeSubpass++; 9344bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pCB->activeSubpassContents = contents; 93455f025a7d647e3257e12a816fa1db078b5fc8ed49Tobin Ehlis TransitionSubpassLayouts(dev_data, pCB, pCB->activeRenderPass, pCB->activeSubpass, 93469a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GetFramebufferState(dev_data, pCB->activeRenderPassBeginInfo.framebuffer)); 934796ebb1e373cc0993339e2ecc1dc47e9918406f87Chris Forbes } 93485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 93495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 935089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL CmdEndRenderPass(VkCommandBuffer commandBuffer) { 93513251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 935256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 9353b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 93549a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pCB = GetCBNode(dev_data, commandBuffer); 935555867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski FRAMEBUFFER_STATE *framebuffer = NULL; 935658c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes if (pCB) { 9357127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis RENDER_PASS_STATE *rp_state = pCB->activeRenderPass; 93589a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis framebuffer = GetFramebufferState(dev_data, pCB->activeFramebuffer); 9359127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis if (rp_state) { 9360127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis if (pCB->activeSubpass != rp_state->createInfo.subpassCount - 1) { 93613251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 93623251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t>(commandBuffer), __LINE__, 93633251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski VALIDATION_ERROR_00460, "DS", "vkCmdEndRenderPass(): Called before reaching final subpass. %s", 93643251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski validation_error_map[VALIDATION_ERROR_00460]); 936502a3382f28fc7c6ec6018165be88aa6fc4f05c9eChris Forbes } 936602a3382f28fc7c6ec6018165be88aa6fc4f05c9eChris Forbes 9367127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis for (size_t i = 0; i < rp_state->createInfo.attachmentCount; ++i) { 9368e3ad4b1284408353cc56a04951c1df1f35a636ceChris Forbes MT_FB_ATTACHMENT_INFO &fb_info = framebuffer->attachments[i]; 9369127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis auto pAttachment = &rp_state->createInfo.pAttachments[i]; 9370bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (FormatSpecificLoadAndStoreOpSettings(pAttachment->format, pAttachment->storeOp, pAttachment->stencilStoreOp, 9371bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VK_ATTACHMENT_STORE_OP_STORE)) { 937258c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes std::function<bool()> function = [=]() { 93739a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis SetImageMemoryValid(dev_data, GetImageState(dev_data, fb_info.image), true); 937458c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes return false; 937558c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes }; 937658c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes pCB->validate_functions.push_back(function); 9377db6ad16f7690669bb664b970a8e5c47abb8db9faChris Forbes } else if (FormatSpecificLoadAndStoreOpSettings(pAttachment->format, pAttachment->storeOp, 9378bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pAttachment->stencilStoreOp, VK_ATTACHMENT_STORE_OP_DONT_CARE)) { 937958c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes std::function<bool()> function = [=]() { 93809a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis SetImageMemoryValid(dev_data, GetImageState(dev_data, fb_info.image), false); 938158c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes return false; 938258c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes }; 938358c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes pCB->validate_functions.push_back(function); 93845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 93855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 93865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 93873251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= outsideRenderPass(dev_data, pCB, "vkCmdEndRenderpass()", VALIDATION_ERROR_00464); 9388eb4c61477130f69f48fdf3ac31cb82104181cc73Chris Forbes skip |= validatePrimaryCommandBuffer(dev_data, pCB, "vkCmdEndRenderPass()", VALIDATION_ERROR_00465); 93893251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdEndRenderPass()", VK_QUEUE_GRAPHICS_BIT, VALIDATION_ERROR_00463); 93903251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateCmd(dev_data, pCB, CMD_ENDRENDERPASS, "vkCmdEndRenderPass()"); 93911ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_ENDRENDERPASS); 93920e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes } 93930e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes lock.unlock(); 93940e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes 93953251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (skip) return; 93960e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes 93974a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.CmdEndRenderPass(commandBuffer); 93980e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes 93990e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes if (pCB) { 94000e21dda98453b5ced1fe7a2ffd5ca4b21847fe09Chris Forbes lock.lock(); 940155867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski TransitionFinalSubpassLayouts(dev_data, pCB, &pCB->activeRenderPassBeginInfo, framebuffer); 940258c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes pCB->activeRenderPass = nullptr; 940358c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes pCB->activeSubpass = 0; 940458c3d40b47b6b30c1e7c508ec14ee67fcd238c93Chris Forbes pCB->activeFramebuffer = VK_NULL_HANDLE; 94055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 94065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 94075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9408a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlisstatic bool logInvalidAttachmentMessage(layer_data *dev_data, VkCommandBuffer secondaryBuffer, uint32_t primaryAttach, 9409a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis uint32_t secondaryAttach, const char *msg) { 9410df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski return log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 9411df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(secondaryBuffer), __LINE__, VALIDATION_ERROR_02059, "DS", 9412df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "vkCmdExecuteCommands() called w/ invalid Secondary Cmd Buffer 0x%" PRIx64 9413df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski " which has a render pass " 9414df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "that is not compatible with the Primary Cmd Buffer current render pass. " 9415df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "Attachment %u is not compatible with %u: %s. %s", 94169bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt reinterpret_cast<uint64_t &>(secondaryBuffer), primaryAttach, secondaryAttach, msg, 94179bd94c6fc216a1d67d5e98542519002fa56d19dbMike Schuchardt validation_error_map[VALIDATION_ERROR_02059]); 94185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 94195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9420a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlisstatic bool validateAttachmentCompatibility(layer_data *dev_data, VkCommandBuffer primaryBuffer, 9421a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis VkRenderPassCreateInfo const *primaryPassCI, uint32_t primaryAttach, 9422a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis VkCommandBuffer secondaryBuffer, VkRenderPassCreateInfo const *secondaryPassCI, 9423e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves uint32_t secondaryAttach, bool is_multi) { 94243251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 9425a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis if (primaryPassCI->attachmentCount <= primaryAttach) { 94265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis primaryAttach = VK_ATTACHMENT_UNUSED; 94275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9428a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis if (secondaryPassCI->attachmentCount <= secondaryAttach) { 94295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis secondaryAttach = VK_ATTACHMENT_UNUSED; 94305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 94315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (primaryAttach == VK_ATTACHMENT_UNUSED && secondaryAttach == VK_ATTACHMENT_UNUSED) { 94323251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 94335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 94345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (primaryAttach == VK_ATTACHMENT_UNUSED) { 94353251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= logInvalidAttachmentMessage(dev_data, secondaryBuffer, primaryAttach, secondaryAttach, 94363251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "The first is unused while the second is not."); 94373251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 94385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 94395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (secondaryAttach == VK_ATTACHMENT_UNUSED) { 94403251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= logInvalidAttachmentMessage(dev_data, secondaryBuffer, primaryAttach, secondaryAttach, 94413251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "The second is unused while the first is not."); 94423251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 94435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9444a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis if (primaryPassCI->pAttachments[primaryAttach].format != secondaryPassCI->pAttachments[secondaryAttach].format) { 94453251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 9446a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis logInvalidAttachmentMessage(dev_data, secondaryBuffer, primaryAttach, secondaryAttach, "They have different formats."); 94475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9448a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis if (primaryPassCI->pAttachments[primaryAttach].samples != secondaryPassCI->pAttachments[secondaryAttach].samples) { 94493251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 9450a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis logInvalidAttachmentMessage(dev_data, secondaryBuffer, primaryAttach, secondaryAttach, "They have different samples."); 94515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9452a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis if (is_multi && primaryPassCI->pAttachments[primaryAttach].flags != secondaryPassCI->pAttachments[secondaryAttach].flags) { 94533251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 9454a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis logInvalidAttachmentMessage(dev_data, secondaryBuffer, primaryAttach, secondaryAttach, "They have different flags."); 94555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 94563251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 94575b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 94585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9459a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlisstatic bool validateSubpassCompatibility(layer_data *dev_data, VkCommandBuffer primaryBuffer, 9460a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis VkRenderPassCreateInfo const *primaryPassCI, VkCommandBuffer secondaryBuffer, 9461a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis VkRenderPassCreateInfo const *secondaryPassCI, const int subpass, bool is_multi) { 94623251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 9463a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis const VkSubpassDescription &primary_desc = primaryPassCI->pSubpasses[subpass]; 9464a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis const VkSubpassDescription &secondary_desc = secondaryPassCI->pSubpasses[subpass]; 94655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t maxInputAttachmentCount = std::max(primary_desc.inputAttachmentCount, secondary_desc.inputAttachmentCount); 94665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < maxInputAttachmentCount; ++i) { 94675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t primary_input_attach = VK_ATTACHMENT_UNUSED, secondary_input_attach = VK_ATTACHMENT_UNUSED; 94685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (i < primary_desc.inputAttachmentCount) { 94695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis primary_input_attach = primary_desc.pInputAttachments[i].attachment; 94705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 94715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (i < secondary_desc.inputAttachmentCount) { 94725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis secondary_input_attach = secondary_desc.pInputAttachments[i].attachment; 94735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 94743251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= validateAttachmentCompatibility(dev_data, primaryBuffer, primaryPassCI, primary_input_attach, secondaryBuffer, 94753251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski secondaryPassCI, secondary_input_attach, is_multi); 94765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 94775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t maxColorAttachmentCount = std::max(primary_desc.colorAttachmentCount, secondary_desc.colorAttachmentCount); 94785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < maxColorAttachmentCount; ++i) { 94795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t primary_color_attach = VK_ATTACHMENT_UNUSED, secondary_color_attach = VK_ATTACHMENT_UNUSED; 94805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (i < primary_desc.colorAttachmentCount) { 94815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis primary_color_attach = primary_desc.pColorAttachments[i].attachment; 94825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 94835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (i < secondary_desc.colorAttachmentCount) { 94845b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis secondary_color_attach = secondary_desc.pColorAttachments[i].attachment; 94855b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 94863251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= validateAttachmentCompatibility(dev_data, primaryBuffer, primaryPassCI, primary_color_attach, secondaryBuffer, 94873251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski secondaryPassCI, secondary_color_attach, is_multi); 94885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t primary_resolve_attach = VK_ATTACHMENT_UNUSED, secondary_resolve_attach = VK_ATTACHMENT_UNUSED; 94895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (i < primary_desc.colorAttachmentCount && primary_desc.pResolveAttachments) { 94905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis primary_resolve_attach = primary_desc.pResolveAttachments[i].attachment; 94915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 94925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (i < secondary_desc.colorAttachmentCount && secondary_desc.pResolveAttachments) { 94935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis secondary_resolve_attach = secondary_desc.pResolveAttachments[i].attachment; 94945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 94953251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= validateAttachmentCompatibility(dev_data, primaryBuffer, primaryPassCI, primary_resolve_attach, secondaryBuffer, 94963251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski secondaryPassCI, secondary_resolve_attach, is_multi); 94975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 94985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis uint32_t primary_depthstencil_attach = VK_ATTACHMENT_UNUSED, secondary_depthstencil_attach = VK_ATTACHMENT_UNUSED; 94995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (primary_desc.pDepthStencilAttachment) { 95005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis primary_depthstencil_attach = primary_desc.pDepthStencilAttachment[0].attachment; 95015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 95025b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (secondary_desc.pDepthStencilAttachment) { 95035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis secondary_depthstencil_attach = secondary_desc.pDepthStencilAttachment[0].attachment; 95045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 95053251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= validateAttachmentCompatibility(dev_data, primaryBuffer, primaryPassCI, primary_depthstencil_attach, secondaryBuffer, 95063251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski secondaryPassCI, secondary_depthstencil_attach, is_multi); 95073251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 95085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 95095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9510a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis// Verify that given renderPass CreateInfo for primary and secondary command buffers are compatible. 9511a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis// This function deals directly with the CreateInfo, there are overloaded versions below that can take the renderPass handle and 9512a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis// will then feed into this function 9513a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlisstatic bool validateRenderPassCompatibility(layer_data *dev_data, VkCommandBuffer primaryBuffer, 9514a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis VkRenderPassCreateInfo const *primaryPassCI, VkCommandBuffer secondaryBuffer, 9515a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis VkRenderPassCreateInfo const *secondaryPassCI) { 95163251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 9517a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis 9518a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis if (primaryPassCI->subpassCount != secondaryPassCI->subpassCount) { 95193251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 95203251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t>(primaryBuffer), __LINE__, DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS", 95213251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkCmdExecuteCommands() called w/ invalid secondary Cmd Buffer 0x%" PRIx64 95223251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski " that has a subpassCount of %u that is incompatible with the primary Cmd Buffer 0x%" PRIx64 95233251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski " that has a subpassCount of %u.", 95243251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t &>(secondaryBuffer), secondaryPassCI->subpassCount, 95253251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t &>(primaryBuffer), primaryPassCI->subpassCount); 9526a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis } else { 9527a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis for (uint32_t i = 0; i < primaryPassCI->subpassCount; ++i) { 95283251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= validateSubpassCompatibility(dev_data, primaryBuffer, primaryPassCI, secondaryBuffer, secondaryPassCI, i, 95293251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski primaryPassCI->subpassCount > 1); 9530a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis } 95315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 95323251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 95335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 95345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9535e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool validateFramebuffer(layer_data *dev_data, VkCommandBuffer primaryBuffer, const GLOBAL_CB_NODE *pCB, 9536e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves VkCommandBuffer secondaryBuffer, const GLOBAL_CB_NODE *pSubCB) { 95373251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 95385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!pSubCB->beginInfo.pInheritanceInfo) { 95393251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 95405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9541c5b97dda856ff837638b3ebb7e231d5507c495a3Chris Forbes VkFramebuffer primary_fb = pCB->activeFramebuffer; 95425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkFramebuffer secondary_fb = pSubCB->beginInfo.pInheritanceInfo->framebuffer; 95435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (secondary_fb != VK_NULL_HANDLE) { 95445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (primary_fb != secondary_fb) { 95453251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 95463251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t>(primaryBuffer), __LINE__, VALIDATION_ERROR_02060, "DS", 95473251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkCmdExecuteCommands() called w/ invalid secondary command buffer 0x%" PRIx64 95483251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski " which has a framebuffer 0x%" PRIx64 95493251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski " that is not the same as the primary command buffer's current active framebuffer 0x%" PRIx64 ". %s", 95503251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t &>(secondaryBuffer), reinterpret_cast<uint64_t &>(secondary_fb), 95513251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t &>(primary_fb), validation_error_map[VALIDATION_ERROR_02060]); 95525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 95539a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto fb = GetFramebufferState(dev_data, secondary_fb); 9554e3ad4b1284408353cc56a04951c1df1f35a636ceChris Forbes if (!fb) { 95553251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 95563251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t>(primaryBuffer), __LINE__, DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS", 95573251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkCmdExecuteCommands() called w/ invalid Cmd Buffer 0x%p " 95583251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "which has invalid framebuffer 0x%" PRIx64 ".", 95593251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski (void *)secondaryBuffer, (uint64_t)(secondary_fb)); 95603251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 95615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 95629a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto cb_renderpass = GetRenderPassState(dev_data, pSubCB->beginInfo.pInheritanceInfo->renderPass); 9563a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis if (cb_renderpass->renderPass != fb->createInfo.renderPass) { 95643251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= validateRenderPassCompatibility(dev_data, secondaryBuffer, fb->renderPassCreateInfo.ptr(), secondaryBuffer, 95653251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski cb_renderpass->createInfo.ptr()); 9566a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis } 95675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 95683251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 95695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 95705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9571e3319189d6f8e3126522df7a5935d2c42f656291Dustin Gravesstatic bool validateSecondaryCommandBufferState(layer_data *dev_data, GLOBAL_CB_NODE *pCB, GLOBAL_CB_NODE *pSubCB) { 95723251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 95735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis unordered_set<int> activeTypes; 95745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto queryObject : pCB->activeQueries) { 95755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto queryPoolData = dev_data->queryPoolMap.find(queryObject.pool); 95765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (queryPoolData != dev_data->queryPoolMap.end()) { 95775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (queryPoolData->second.createInfo.queryType == VK_QUERY_TYPE_PIPELINE_STATISTICS && 95785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pSubCB->beginInfo.pInheritanceInfo) { 95795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkQueryPipelineStatisticFlags cmdBufStatistics = pSubCB->beginInfo.pInheritanceInfo->pipelineStatistics; 95805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if ((cmdBufStatistics & queryPoolData->second.createInfo.pipelineStatistics) != cmdBufStatistics) { 95813251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 95823251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t>(pCB->commandBuffer), 95833251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski __LINE__, VALIDATION_ERROR_02065, "DS", 95843251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkCmdExecuteCommands() called w/ invalid Cmd Buffer 0x%p " 95853251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "which has invalid active query pool 0x%" PRIx64 95863251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski ". Pipeline statistics is being queried so the command " 95873251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "buffer must have all bits set on the queryPool. %s", 95883251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski pCB->commandBuffer, reinterpret_cast<const uint64_t &>(queryPoolData->first), 95893251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski validation_error_map[VALIDATION_ERROR_02065]); 95905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 95915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 95925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis activeTypes.insert(queryPoolData->second.createInfo.queryType); 95935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 95945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 95955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto queryObject : pSubCB->startedQueries) { 95965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto queryPoolData = dev_data->queryPoolMap.find(queryObject.pool); 95975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (queryPoolData != dev_data->queryPoolMap.end() && activeTypes.count(queryPoolData->second.createInfo.queryType)) { 95983251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 9599df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 9600df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS", 9601df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "vkCmdExecuteCommands() called w/ invalid Cmd Buffer 0x%p " 9602df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "which has invalid active query pool 0x%" PRIx64 9603df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "of type %d but a query of that type has been started on " 9604df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "secondary Cmd Buffer 0x%p.", 9605df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski pCB->commandBuffer, reinterpret_cast<const uint64_t &>(queryPoolData->first), 9606df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski queryPoolData->second.createInfo.queryType, pSubCB->commandBuffer); 96075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 96085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 96097bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski 96109a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto primary_pool = GetCommandPoolNode(dev_data, pCB->createInfo.commandPool); 96119a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto secondary_pool = GetCommandPoolNode(dev_data, pSubCB->createInfo.commandPool); 96127bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski if (primary_pool && secondary_pool && (primary_pool->queueFamilyIndex != secondary_pool->queueFamilyIndex)) { 96133251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 9614226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 9615226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis reinterpret_cast<uint64_t>(pSubCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_QUEUE_FAMILY, "DS", 9616226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "vkCmdExecuteCommands(): Primary command buffer 0x%p" 9617226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis " created in queue family %d has secondary command buffer 0x%p created in queue family %d.", 9618226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis pCB->commandBuffer, primary_pool->queueFamilyIndex, pSubCB->commandBuffer, secondary_pool->queueFamilyIndex); 96197bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski } 96207bd96b29f4b8df99339ff1f7bc64f2f8940f8d25Mark Lobodzinski 96213251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski return skip; 96225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 96235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9624bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t commandBuffersCount, 9625bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkCommandBuffer *pCommandBuffers) { 96263251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 962756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 9628b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 96299a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis GLOBAL_CB_NODE *pCB = GetCBNode(dev_data, commandBuffer); 96305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB) { 96315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis GLOBAL_CB_NODE *pSubCB = NULL; 96325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < commandBuffersCount; i++) { 96339a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis pSubCB = GetCBNode(dev_data, pCommandBuffers[i]); 96340a8b955c23012196339f3c10ffedc631ea0f7c58Tobin Ehlis assert(pSubCB); 96350a8b955c23012196339f3c10ffedc631ea0f7c58Tobin Ehlis if (VK_COMMAND_BUFFER_LEVEL_PRIMARY == pSubCB->createInfo.level) { 96363251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 9637df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 963860f59be7ded9ccf2d57c36b2e0974cc2798cf844Tobin Ehlis reinterpret_cast<uint64_t>(pCommandBuffers[i]), __LINE__, VALIDATION_ERROR_00156, "DS", 9639df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "vkCmdExecuteCommands() called w/ Primary Cmd Buffer 0x%p in element %u of pCommandBuffers " 9640df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski "array. All cmd buffers in pCommandBuffers array must be secondary. %s", 964160f59be7ded9ccf2d57c36b2e0974cc2798cf844Tobin Ehlis pCommandBuffers[i], i, validation_error_map[VALIDATION_ERROR_00156]); 9642cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else if (pCB->activeRenderPass) { // Secondary CB w/i RenderPass must have *CONTINUE_BIT set 96439a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto secondary_rp_state = GetRenderPassState(dev_data, pSubCB->beginInfo.pInheritanceInfo->renderPass); 96445b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!(pSubCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT)) { 96453251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg( 96465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 9647df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(pCommandBuffers[i]), __LINE__, VALIDATION_ERROR_02057, "DS", 9648414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller "vkCmdExecuteCommands(): Secondary Command Buffer (0x%p) executed within render pass (0x%" PRIxLEAST64 96494b6738a6adb4e813d66234defee5d18b7c84340dMike Weiblen ") must have had vkBeginCommandBuffer() called w/ VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT set. %s", 9650226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis pCommandBuffers[i], (uint64_t)pCB->activeRenderPass->renderPass, 96514b6738a6adb4e813d66234defee5d18b7c84340dMike Weiblen validation_error_map[VALIDATION_ERROR_02057]); 96525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } else { 96535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Make sure render pass is compatible with parent command buffer pass if has continue 9654127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis if (pCB->activeRenderPass->renderPass != secondary_rp_state->renderPass) { 96553251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= validateRenderPassCompatibility(dev_data, commandBuffer, pCB->activeRenderPass->createInfo.ptr(), 96563251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski pCommandBuffers[i], secondary_rp_state->createInfo.ptr()); 9657a092085c225bbc24edb29cd34ca6b30889f7e111Tobin Ehlis } 96581af6125615cd6dd9735d32e2ee8684abeff28d41Tobin Ehlis // If framebuffer for secondary CB is not NULL, then it must match active FB from primaryCB 96593251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= validateFramebuffer(dev_data, commandBuffer, pCB, pCommandBuffers[i], pSubCB); 96605b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 96615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis string errorString = ""; 96621af6125615cd6dd9735d32e2ee8684abeff28d41Tobin Ehlis // secondaryCB must have been created w/ RP compatible w/ primaryCB active renderpass 9663127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis if ((pCB->activeRenderPass->renderPass != secondary_rp_state->renderPass) && 9664fb13c2c4174108223d9f8e43084020eb09115ed6Chris Forbes !verify_renderpass_compatibility(dev_data, pCB->activeRenderPass->createInfo.ptr(), 9665127937bcdb5817ee4568887c298ce36c88f3c58bTobin Ehlis secondary_rp_state->createInfo.ptr(), errorString)) { 96663251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg( 96675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 9668df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(pCommandBuffers[i]), __LINE__, DRAWSTATE_RENDERPASS_INCOMPATIBLE, "DS", 9669414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller "vkCmdExecuteCommands(): Secondary Command Buffer (0x%p) w/ render pass (0x%" PRIxLEAST64 9670414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller ") is incompatible w/ primary command buffer (0x%p) w/ render pass (0x%" PRIxLEAST64 ") due to: %s", 9671226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis pCommandBuffers[i], (uint64_t)pSubCB->beginInfo.pInheritanceInfo->renderPass, commandBuffer, 9672ee691f5c5fa87aac3750454d2bca2cb582e4e817Chris Forbes (uint64_t)pCB->activeRenderPass->renderPass, errorString.c_str()); 96735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 96745b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 96755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODO(mlentine): Move more logic into this method 96763251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= validateSecondaryCommandBufferState(dev_data, pCB, pSubCB); 96773251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= validateCommandBufferState(dev_data, pSubCB, "vkCmdExecuteCommands()", 0); 96785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Secondary cmdBuffers are considered pending execution starting w/ 96795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // being recorded 96805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (!(pSubCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT)) { 96815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (dev_data->globalInFlightCmdBuffers.find(pSubCB->commandBuffer) != dev_data->globalInFlightCmdBuffers.end()) { 96823251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 96833251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t>(pCB->commandBuffer), 96843251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski __LINE__, VALIDATION_ERROR_00154, "DS", 96853251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Attempt to simultaneously execute command buffer 0x%p" 96863251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski " without VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT set! %s", 96873251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski pCB->commandBuffer, validation_error_map[VALIDATION_ERROR_00154]); 96885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 96895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT) { 96905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Warn that non-simultaneous secondary cmd buffer renders primary non-simultaneous 96913251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg( 96925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 9693df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<uint64_t>(pCommandBuffers[i]), __LINE__, DRAWSTATE_INVALID_CB_SIMULTANEOUS_USE, "DS", 9694226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "vkCmdExecuteCommands(): Secondary Command Buffer (0x%p) " 9695226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "does not have VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT set and will cause primary command buffer " 9696226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis "(0x%p) to be treated as if it does not have VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT " 969783b40cb743b7d87753e7503b148fef660ca45289Tobin Ehlis "set, even though it does.", 9698226a75bff897619b86cc227cf1196b5e245fb96dTobin Ehlis pCommandBuffers[i], pCB->commandBuffer); 96995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->beginInfo.flags &= ~VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT; 97005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 97015b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9702f71dd305f197826a61f398bff725267a20ea1d90Chris Forbes if (!pCB->activeQueries.empty() && !dev_data->enabled_features.inheritedQueries) { 97033251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 9704cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 9705cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski reinterpret_cast<uint64_t>(pCommandBuffers[i]), __LINE__, VALIDATION_ERROR_02062, "DS", 9706cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkCmdExecuteCommands(): Secondary Command Buffer " 9707cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "(0x%p) cannot be submitted with a query in " 9708cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "flight and inherited queries not " 9709cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "supported on this device. %s", 9710cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pCommandBuffers[i], validation_error_map[VALIDATION_ERROR_02062]); 97115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 97128567fecbf563420f5900ade277ca68908aa87259Tobin Ehlis // Propagate layout transitions to the primary cmd buffer 97138567fecbf563420f5900ade277ca68908aa87259Tobin Ehlis for (auto ilm_entry : pSubCB->imageLayoutMap) { 971455867dbad6ae423b3bd78c15f6771031a710b5adMark Lobodzinski SetLayout(dev_data, pCB, ilm_entry.first, ilm_entry.second); 97158567fecbf563420f5900ade277ca68908aa87259Tobin Ehlis } 97165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pSubCB->primaryCommandBuffer = pCB->commandBuffer; 97175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis pCB->secondaryCommandBuffers.insert(pSubCB->commandBuffer); 97185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->globalInFlightCmdBuffers.insert(pSubCB->commandBuffer); 9719d4ee9fdb2def1e9dc70c5627c9103e264471b8ebMichael Lentine for (auto &function : pSubCB->queryUpdates) { 9720d4ee9fdb2def1e9dc70c5627c9103e264471b8ebMichael Lentine pCB->queryUpdates.push_back(function); 9721d4ee9fdb2def1e9dc70c5627c9103e264471b8ebMichael Lentine } 97225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9723eb4c61477130f69f48fdf3ac31cb82104181cc73Chris Forbes skip |= validatePrimaryCommandBuffer(dev_data, pCB, "vkCmdExecuteCommands()", VALIDATION_ERROR_00163); 9724f5a52627a6576d3d532cd1f2e1be6d9987aeda7fChris Forbes skip |= ValidateCmdQueueFlags(dev_data, pCB, "vkCmdExecuteCommands()", 97253251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski VK_QUEUE_TRANSFER_BIT | VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, VALIDATION_ERROR_00162); 9726f5a52627a6576d3d532cd1f2e1be6d9987aeda7fChris Forbes skip |= ValidateCmd(dev_data, pCB, CMD_EXECUTECOMMANDS, "vkCmdExecuteCommands()"); 97271ae739f43f52f7a8bb3a58dcdeac617ddd30b16cTobin Ehlis UpdateCmdBufferLastCmd(pCB, CMD_EXECUTECOMMANDS); 97285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9729b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 97303251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) dev_data->dispatch_table.CmdExecuteCommands(commandBuffer, commandBuffersCount, pCommandBuffers); 97315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 97325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9733bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL MapMemory(VkDevice device, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size, VkFlags flags, 9734bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski void **ppData) { 973556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 97365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 97373251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 97385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 9739b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 97409a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis DEVICE_MEM_INFO *mem_info = GetMemObjInfo(dev_data, mem); 9741cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis if (mem_info) { 9742f541bf53dee6daf82a4c8304354eac599a884d29Tobin Ehlis // TODO : This could me more fine-grained to track just region that is valid 9743f541bf53dee6daf82a4c8304354eac599a884d29Tobin Ehlis mem_info->global_valid = true; 9744623548a271287ae55415e45e3c654ee66d4e79ffTobin Ehlis auto end_offset = (VK_WHOLE_SIZE == size) ? mem_info->alloc_info.allocationSize - 1 : offset + size - 1; 97453251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateMapImageLayouts(dev_data, device, mem_info, offset, end_offset); 9746cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis // TODO : Do we need to create new "bound_range" for the mapped range? 9747623548a271287ae55415e45e3c654ee66d4e79ffTobin Ehlis SetMemRangesValid(dev_data, mem_info, offset, end_offset); 9748cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis if ((dev_data->phys_dev_mem_props.memoryTypes[mem_info->alloc_info.memoryTypeIndex].propertyFlags & 9749b1b606d27e8c4179534d7bbb48ce217429e37414Tobin Ehlis VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0) { 97503251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 97513251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski (uint64_t)mem, __LINE__, VALIDATION_ERROR_00629, "MEM", 97523251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Mapping Memory without VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT set: mem obj 0x%" PRIxLEAST64 ". %s", 97533251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski (uint64_t)mem, validation_error_map[VALIDATION_ERROR_00629]); 97545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 97555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 97563251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateMapMemRange(dev_data, mem, offset, size); 9757b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 97585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 97593251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) { 97604a0754042cf090e131e9e769d8a3633c228625beChris Forbes result = dev_data->dispatch_table.MapMemory(device, mem, offset, size, flags, ppData); 97617c0012acb5327961b0a5191434a08e5fa788786dTobin Ehlis if (VK_SUCCESS == result) { 97627c0012acb5327961b0a5191434a08e5fa788786dTobin Ehlis lock.lock(); 9763cf17f50f6489504c0d8151c46d6f77404ce2ffffTobin Ehlis // TODO : What's the point of this range? See comment on creating new "bound_range" above, which may replace this 97647c0012acb5327961b0a5191434a08e5fa788786dTobin Ehlis storeMemRanges(dev_data, mem, offset, size); 97655f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski initializeAndTrackMemory(dev_data, mem, offset, size, ppData); 97667c0012acb5327961b0a5191434a08e5fa788786dTobin Ehlis lock.unlock(); 97677c0012acb5327961b0a5191434a08e5fa788786dTobin Ehlis } 97685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 97695b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 97705b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 97715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 977289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR void VKAPI_CALL UnmapMemory(VkDevice device, VkDeviceMemory mem) { 977356e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 97743251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 97755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9776b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 97773251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= deleteMemRanges(dev_data, mem); 9778b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 97793251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) { 97804a0754042cf090e131e9e769d8a3633c228625beChris Forbes dev_data->dispatch_table.UnmapMemory(device, mem); 97815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 97825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 97835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 97848860b85a52096f9f9b28616bc37feed505497a54Chris Forbesstatic bool validateMemoryIsMapped(layer_data *dev_data, const char *funcName, uint32_t memRangeCount, 9785e3319189d6f8e3126522df7a5935d2c42f656291Dustin Graves const VkMappedMemoryRange *pMemRanges) { 9786c7ee6f2fe100c1aacfaa0872832717c906bb8a4aMark Lobodzinski bool skip = false; 97875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < memRangeCount; ++i) { 97889a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto mem_info = GetMemObjInfo(dev_data, pMemRanges[i].memory); 978957fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis if (mem_info) { 9790f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski if (pMemRanges[i].size == VK_WHOLE_SIZE) { 9791f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski if (mem_info->mem_range.offset > pMemRanges[i].offset) { 9792cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 9793cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, (uint64_t)pMemRanges[i].memory, __LINE__, 9794cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VALIDATION_ERROR_00643, "MEM", "%s: Flush/Invalidate offset (" PRINTF_SIZE_T_SPECIFIER 9795cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski ") is less than Memory Object's offset " 9796cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "(" PRINTF_SIZE_T_SPECIFIER "). %s", 9797cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski funcName, static_cast<size_t>(pMemRanges[i].offset), 9798cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski static_cast<size_t>(mem_info->mem_range.offset), validation_error_map[VALIDATION_ERROR_00643]); 9799f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski } 9800f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski } else { 9801f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski const uint64_t data_end = (mem_info->mem_range.size == VK_WHOLE_SIZE) 9802f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski ? mem_info->alloc_info.allocationSize 9803f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski : (mem_info->mem_range.offset + mem_info->mem_range.size); 9804f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski if ((mem_info->mem_range.offset > pMemRanges[i].offset) || 9805f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski (data_end < (pMemRanges[i].offset + pMemRanges[i].size))) { 9806c7ee6f2fe100c1aacfaa0872832717c906bb8a4aMark Lobodzinski skip |= 9807f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 9808f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski (uint64_t)pMemRanges[i].memory, __LINE__, VALIDATION_ERROR_00642, "MEM", 9809f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski "%s: Flush/Invalidate size or offset (" PRINTF_SIZE_T_SPECIFIER ", " PRINTF_SIZE_T_SPECIFIER 9810f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski ") exceed the Memory Object's upper-bound " 9811f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski "(" PRINTF_SIZE_T_SPECIFIER "). %s", 9812f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski funcName, static_cast<size_t>(pMemRanges[i].offset + pMemRanges[i].size), 9813f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski static_cast<size_t>(pMemRanges[i].offset), static_cast<size_t>(data_end), 9814f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski validation_error_map[VALIDATION_ERROR_00642]); 9815f0b0053ba47c1fc2ee173cfef0eaf63356cd4b0cMark Lobodzinski } 98165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 98175b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 98185b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9819c7ee6f2fe100c1aacfaa0872832717c906bb8a4aMark Lobodzinski return skip; 98205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 98215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9822bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinskistatic bool ValidateAndCopyNoncoherentMemoryToDriver(layer_data *dev_data, uint32_t mem_range_count, 9823bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski const VkMappedMemoryRange *mem_ranges) { 9824bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski bool skip = false; 9825bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski for (uint32_t i = 0; i < mem_range_count; ++i) { 98269a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto mem_info = GetMemObjInfo(dev_data, mem_ranges[i].memory); 982757fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis if (mem_info) { 98285f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski if (mem_info->shadow_copy) { 98295f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski VkDeviceSize size = (mem_info->mem_range.size != VK_WHOLE_SIZE) 98305f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski ? mem_info->mem_range.size 9831d8a53ade6b5501256798a8b4ec0bc14f72adc1faTobin Ehlis : (mem_info->alloc_info.allocationSize - mem_info->mem_range.offset); 98325f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski char *data = static_cast<char *>(mem_info->shadow_copy); 98335f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski for (uint64_t j = 0; j < mem_info->shadow_pad_size; ++j) { 98345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (data[j] != NoncoherentMemoryFillValue) { 9835bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 9836bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, (uint64_t)mem_ranges[i].memory, __LINE__, 9837bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski MEMTRACK_INVALID_MAP, "MEM", "Memory underflow was detected on mem obj 0x%" PRIxLEAST64, 9838bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski (uint64_t)mem_ranges[i].memory); 98395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 98405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 98415f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski for (uint64_t j = (size + mem_info->shadow_pad_size); j < (2 * mem_info->shadow_pad_size + size); ++j) { 98425b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (data[j] != NoncoherentMemoryFillValue) { 9843bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 9844bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, (uint64_t)mem_ranges[i].memory, __LINE__, 9845bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski MEMTRACK_INVALID_MAP, "MEM", "Memory overflow was detected on mem obj 0x%" PRIxLEAST64, 9846bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski (uint64_t)mem_ranges[i].memory); 98475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 98485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 98495f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski memcpy(mem_info->p_driver_data, static_cast<void *>(data + mem_info->shadow_pad_size), (size_t)(size)); 98505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 98515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 98525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 9853bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski return skip; 98545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 98555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9856bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinskistatic void CopyNoncoherentMemoryFromDriver(layer_data *dev_data, uint32_t mem_range_count, const VkMappedMemoryRange *mem_ranges) { 9857bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski for (uint32_t i = 0; i < mem_range_count; ++i) { 98589a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto mem_info = GetMemObjInfo(dev_data, mem_ranges[i].memory); 98595f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski if (mem_info && mem_info->shadow_copy) { 98605f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski VkDeviceSize size = (mem_info->mem_range.size != VK_WHOLE_SIZE) 98615f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski ? mem_info->mem_range.size 98625f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski : (mem_info->alloc_info.allocationSize - mem_ranges[i].offset); 98635f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski char *data = static_cast<char *>(mem_info->shadow_copy); 98645f06b9eba1bf89d4066ca44120dcb72c4cf44104Mark Lobodzinski memcpy(data + mem_info->shadow_pad_size, mem_info->p_driver_data, (size_t)(size)); 98659e21e56fc23ade48efd3752d2e2729895eb90349Mark Lobodzinski } 98669e21e56fc23ade48efd3752d2e2729895eb90349Mark Lobodzinski } 98679e21e56fc23ade48efd3752d2e2729895eb90349Mark Lobodzinski} 98689e21e56fc23ade48efd3752d2e2729895eb90349Mark Lobodzinski 9869ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinskistatic bool ValidateMappedMemoryRangeDeviceLimits(layer_data *dev_data, const char *func_name, uint32_t mem_range_count, 9870ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski const VkMappedMemoryRange *mem_ranges) { 9871ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski bool skip = false; 9872ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski for (uint32_t i = 0; i < mem_range_count; ++i) { 9873ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski uint64_t atom_size = dev_data->phys_dev_properties.properties.limits.nonCoherentAtomSize; 987416769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton if (SafeModulo(mem_ranges[i].offset, atom_size) != 0) { 9875df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 9876df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<const uint64_t &>(mem_ranges->memory), __LINE__, VALIDATION_ERROR_00644, "MEM", 9877ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski "%s: Offset in pMemRanges[%d] is 0x%" PRIxLEAST64 9878ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski ", which is not a multiple of VkPhysicalDeviceLimits::nonCoherentAtomSize (0x%" PRIxLEAST64 "). %s", 9879ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski func_name, i, mem_ranges[i].offset, atom_size, validation_error_map[VALIDATION_ERROR_00644]); 9880ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski } 988116769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton if ((mem_ranges[i].size != VK_WHOLE_SIZE) && (SafeModulo(mem_ranges[i].size, atom_size) != 0)) { 9882df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 9883df7c947594a31bb74004ab2ca335ece9b60721b6Mark Lobodzinski reinterpret_cast<const uint64_t &>(mem_ranges->memory), __LINE__, VALIDATION_ERROR_00645, "MEM", 9884ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski "%s: Size in pMemRanges[%d] is 0x%" PRIxLEAST64 9885ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski ", which is not a multiple of VkPhysicalDeviceLimits::nonCoherentAtomSize (0x%" PRIxLEAST64 "). %s", 9886ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski func_name, i, mem_ranges[i].size, atom_size, validation_error_map[VALIDATION_ERROR_00645]); 9887ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski } 9888ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski } 9889ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski return skip; 9890ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski} 9891ba16c7616eb49c78dc76eb7682d650287ad8614dMark Lobodzinski 989280e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinskistatic bool PreCallValidateFlushMappedMemoryRanges(layer_data *dev_data, uint32_t mem_range_count, 989380e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski const VkMappedMemoryRange *mem_ranges) { 989480e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski bool skip = false; 989580e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski std::lock_guard<std::mutex> lock(global_lock); 989680e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski skip |= ValidateAndCopyNoncoherentMemoryToDriver(dev_data, mem_range_count, mem_ranges); 989780e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski skip |= validateMemoryIsMapped(dev_data, "vkFlushMappedMemoryRanges", mem_range_count, mem_ranges); 989880e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski return skip; 989980e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski} 990080e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski 9901bba0de708d942e9a2187158915856995db1c5a4dMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL FlushMappedMemoryRanges(VkDevice device, uint32_t memRangeCount, 9902bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski const VkMappedMemoryRange *pMemRanges) { 99035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 990456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 99055b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 990680e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski if (!PreCallValidateFlushMappedMemoryRanges(dev_data, memRangeCount, pMemRanges)) { 99074a0754042cf090e131e9e769d8a3633c228625beChris Forbes result = dev_data->dispatch_table.FlushMappedMemoryRanges(device, memRangeCount, pMemRanges); 99085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 99095b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 99105b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 99115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 991280e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinskistatic bool PreCallValidateInvalidateMappedMemoryRanges(layer_data *dev_data, uint32_t mem_range_count, 991380e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski const VkMappedMemoryRange *mem_ranges) { 991480e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski bool skip = false; 991580e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski std::lock_guard<std::mutex> lock(global_lock); 991680e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski skip |= validateMemoryIsMapped(dev_data, "vkInvalidateMappedMemoryRanges", mem_range_count, mem_ranges); 991780e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski return skip; 991880e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski} 991980e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski 992080e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinskistatic void PostCallRecordInvalidateMappedMemoryRanges(layer_data *dev_data, uint32_t mem_range_count, 992180e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski const VkMappedMemoryRange *mem_ranges) { 992280e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski std::lock_guard<std::mutex> lock(global_lock); 992380e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski // Update our shadow copy with modified driver data 992480e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski CopyNoncoherentMemoryFromDriver(dev_data, mem_range_count, mem_ranges); 992580e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski} 992680e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski 9927bba0de708d942e9a2187158915856995db1c5a4dMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL InvalidateMappedMemoryRanges(VkDevice device, uint32_t memRangeCount, 9928bba0de708d942e9a2187158915856995db1c5a4dMark Lobodzinski const VkMappedMemoryRange *pMemRanges) { 99295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 993056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 99315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 993280e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski if (!PreCallValidateInvalidateMappedMemoryRanges(dev_data, memRangeCount, pMemRanges)) { 99334a0754042cf090e131e9e769d8a3633c228625beChris Forbes result = dev_data->dispatch_table.InvalidateMappedMemoryRanges(device, memRangeCount, pMemRanges); 993480e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski if (result == VK_SUCCESS) { 993580e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski PostCallRecordInvalidateMappedMemoryRanges(dev_data, memRangeCount, pMemRanges); 993680e8617d44ad5727efb3da174951080b54b21cd8Mark Lobodzinski } 99375b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 99385b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 99395b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 99405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 9941160335c453ec51cc48bdef78e8befdb3c86ff292Cort Strattonstatic bool PreCallValidateBindImageMemory(layer_data *dev_data, VkImage image, IMAGE_STATE *image_state, VkDeviceMemory mem, 9942160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton VkDeviceSize memoryOffset) { 99430109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski bool skip = false; 99441facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis if (image_state) { 9945160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton std::unique_lock<std::mutex> lock(global_lock); 994694c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis // Track objects tied to memory 994747aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski uint64_t image_handle = reinterpret_cast<uint64_t &>(image); 99487a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski skip = ValidateSetMemBinding(dev_data, mem, image_handle, kVulkanObjectTypeImage, "vkBindImageMemory()"); 9949ff3ef1181960319d2268e82dae075726f650c553Tobin Ehlis if (!image_state->memory_requirements_checked) { 9950ff3ef1181960319d2268e82dae075726f650c553Tobin Ehlis // There's not an explicit requirement in the spec to call vkGetImageMemoryRequirements() prior to calling 9951341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton // BindImageMemory but it's implied in that memory being bound must conform with VkMemoryRequirements from 9952341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton // vkGetImageMemoryRequirements() 99530109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 99540109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski image_handle, __LINE__, DRAWSTATE_INVALID_IMAGE, "DS", 99550109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski "vkBindImageMemory(): Binding memory to image 0x%" PRIxLEAST64 99560109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski " but vkGetImageMemoryRequirements() has not been called on that image.", 99570109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski image_handle); 9958ff3ef1181960319d2268e82dae075726f650c553Tobin Ehlis // Make the call for them so we can verify the state 9959ff3ef1181960319d2268e82dae075726f650c553Tobin Ehlis lock.unlock(); 9960341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton dev_data->dispatch_table.GetImageMemoryRequirements(dev_data->device, image, &image_state->requirements); 9961ff3ef1181960319d2268e82dae075726f650c553Tobin Ehlis lock.lock(); 9962ff3ef1181960319d2268e82dae075726f650c553Tobin Ehlis } 996347aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski 99640ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton // Validate bound memory range information 99659a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto mem_info = GetMemObjInfo(dev_data, mem); 996657fc8e28c2e16118f9827e3ae1b107a27e0451a2Tobin Ehlis if (mem_info) { 99670ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton skip |= ValidateInsertImageMemoryRange(dev_data, image, mem_info, memoryOffset, image_state->requirements, 99680ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton image_state->createInfo.tiling == VK_IMAGE_TILING_LINEAR, "vkBindImageMemory()"); 996974300755ed9ec780d6073af71e47f201217008d6Cort Stratton skip |= ValidateMemoryTypes(dev_data, mem_info, image_state->requirements.memoryTypeBits, "vkBindImageMemory()", 99700109928beb33325a442d7e3e7f38e73edf9cc38bMark Lobodzinski VALIDATION_ERROR_00806); 997147aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski } 9972160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton 9973160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton // Validate memory requirements alignment 997416769f6b2a7721e391952a97f010cbb530e4f211Dave Houlton if (SafeModulo(memoryOffset, image_state->requirements.alignment) != 0) { 9975160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 9976160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton image_handle, __LINE__, VALIDATION_ERROR_02178, "DS", 9977160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton "vkBindImageMemory(): memoryOffset is 0x%" PRIxLEAST64 9978160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton " but must be an integer multiple of the " 9979160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton "VkMemoryRequirements::alignment value 0x%" PRIxLEAST64 9980160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton ", returned from a call to vkGetImageMemoryRequirements with image. %s", 9981160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton memoryOffset, image_state->requirements.alignment, validation_error_map[VALIDATION_ERROR_02178]); 9982160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton } 9983160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton 9984160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton // Validate memory requirements size 9985160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton if (image_state->requirements.size > mem_info->alloc_info.allocationSize - memoryOffset) { 9986160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, 9987160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton image_handle, __LINE__, VALIDATION_ERROR_02179, "DS", 9988160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton "vkBindImageMemory(): memory size minus memoryOffset is 0x%" PRIxLEAST64 9989160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton " but must be at least as large as " 9990160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton "VkMemoryRequirements::size value 0x%" PRIxLEAST64 9991160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton ", returned from a call to vkGetImageMemoryRequirements with image. %s", 9992160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton mem_info->alloc_info.allocationSize - memoryOffset, image_state->requirements.size, 9993160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton validation_error_map[VALIDATION_ERROR_02179]); 9994160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton } 9995341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton } 9996341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton return skip; 9997341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton} 999847aaf733d7394bda75c6de24289efe6b281e3cffMark Lobodzinski 9999160335c453ec51cc48bdef78e8befdb3c86ff292Cort Strattonstatic void PostCallRecordBindImageMemory(layer_data *dev_data, VkImage image, IMAGE_STATE *image_state, VkDeviceMemory mem, 10000160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton VkDeviceSize memoryOffset) { 10001341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton if (image_state) { 10002160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton std::unique_lock<std::mutex> lock(global_lock); 100030ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton // Track bound memory range information 100040ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton auto mem_info = GetMemObjInfo(dev_data, mem); 100050ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton if (mem_info) { 100060ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton InsertImageMemoryRange(dev_data, image, mem_info, memoryOffset, image_state->requirements, 100070ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton image_state->createInfo.tiling == VK_IMAGE_TILING_LINEAR); 100080ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton } 100090ee7762cdcbfd554dd6a71c5ea48eec5e2a4a213Cort Stratton 10010c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton // Track objects tied to memory 10011c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton uint64_t image_handle = reinterpret_cast<uint64_t &>(image); 100127a9423788398dbeb6d1fe0354a66123b61afda96Mark Lobodzinski SetMemBinding(dev_data, mem, image_handle, kVulkanObjectTypeImage, "vkBindImageMemory()"); 10013c18f059542c30f6b37f8a654df020be38adfade6Cort Stratton 10014341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton image_state->binding.mem = mem; 10015341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton image_state->binding.offset = memoryOffset; 10016341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton image_state->binding.size = image_state->requirements.size; 10017341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton } 10018341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton} 10019341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton 10020341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort StrattonVKAPI_ATTR VkResult VKAPI_CALL BindImageMemory(VkDevice device, VkImage image, VkDeviceMemory mem, VkDeviceSize memoryOffset) { 10021341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 10022341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 10023160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton auto image_state = GetImageState(dev_data, image); 10024160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton bool skip = PreCallValidateBindImageMemory(dev_data, image, image_state, mem, memoryOffset); 10025341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton if (!skip) { 10026341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton result = dev_data->dispatch_table.BindImageMemory(device, image, mem, memoryOffset); 10027341d357dc354e888bfdc05b5dfd8c1cabe8417e0Cort Stratton if (result == VK_SUCCESS) { 10028160335c453ec51cc48bdef78e8befdb3c86ff292Cort Stratton PostCallRecordBindImageMemory(dev_data, image, image_state, mem, memoryOffset); 1002994c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis } 100305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 100315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 100325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 100335b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1003489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL SetEvent(VkDevice device, VkEvent event) { 100353251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 100363ee1d6057ee6c49b9dbbeb067b7fd149bdba7b5cTobin Ehlis VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 1003756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 10038b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 100399a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto event_state = GetEventNode(dev_data, event); 100404710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis if (event_state) { 100414710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis event_state->needsSignaled = false; 100424710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis event_state->stageMask = VK_PIPELINE_STAGE_HOST_BIT; 100434710dda89a1dd2e023334d4eda710a394b211cdcTobin Ehlis if (event_state->write_in_use) { 100443251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT, 100453251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<const uint64_t &>(event), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS", 100463251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Cannot call vkSetEvent() on event 0x%" PRIxLEAST64 " that is already in use by a command buffer.", 100473251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<const uint64_t &>(event)); 100483ee1d6057ee6c49b9dbbeb067b7fd149bdba7b5cTobin Ehlis } 100493ee1d6057ee6c49b9dbbeb067b7fd149bdba7b5cTobin Ehlis } 10050b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 100516fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis // Host setting event is visible to all queues immediately so update stageMask for any queue that's seen this event 100526fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis // TODO : For correctness this needs separate fix to verify that app doesn't make incorrect assumptions about the 100536fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis // ordering of this command in relation to vkCmd[Set|Reset]Events (see GH297) 100546fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis for (auto queue_data : dev_data->queueMap) { 100556fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis auto event_entry = queue_data.second.eventToStageMap.find(event); 100566fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis if (event_entry != queue_data.second.eventToStageMap.end()) { 100576fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis event_entry->second |= VK_PIPELINE_STAGE_HOST_BIT; 100586fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis } 100596fcff21b8cce5159fdfa317e612f75f5ea6a189eTobin Ehlis } 100603251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) result = dev_data->dispatch_table.SetEvent(device, event); 100615b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 100625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 100635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10064bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL QueueBindSparse(VkQueue queue, uint32_t bindInfoCount, const VkBindSparseInfo *pBindInfo, 10065bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkFence fence) { 1006656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map); 100675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; 100683251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 10069b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 100709a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pFence = GetFenceNode(dev_data, fence); 100719a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pQueue = GetQueueState(dev_data, queue); 10072651d92815dfff917308137bb67aacccc4f60df86Chris Forbes 100734b38d3aa8b6be6a7f5bebb472ab439da0562824fTobin Ehlis // First verify that fence is not in use 100743251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateFenceForSubmit(dev_data, pFence); 10075651d92815dfff917308137bb67aacccc4f60df86Chris Forbes 100769867daedbf52debc77d6568162ee21e071699b80Chris Forbes if (pFence) { 1007793ccd9708dad3ffb58a3fc09a3d61cc5fe1569f8Mark Lobodzinski SubmitFence(pQueue, pFence, std::max(1u, bindInfoCount)); 100784b38d3aa8b6be6a7f5bebb472ab439da0562824fTobin Ehlis } 10079651d92815dfff917308137bb67aacccc4f60df86Chris Forbes 100801344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis for (uint32_t bindIdx = 0; bindIdx < bindInfoCount; ++bindIdx) { 100811344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis const VkBindSparseInfo &bindInfo = pBindInfo[bindIdx]; 100825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // Track objects tied to memory 100831344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis for (uint32_t j = 0; j < bindInfo.bufferBindCount; j++) { 100841344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis for (uint32_t k = 0; k < bindInfo.pBufferBinds[j].bindCount; k++) { 10085f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis auto sparse_binding = bindInfo.pBufferBinds[j].pBinds[k]; 10086f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis if (SetSparseMemBinding(dev_data, {sparse_binding.memory, sparse_binding.memoryOffset, sparse_binding.size}, 10087ece0e981ee4a5ad2572d146a89fc64d699d79f36Chris Forbes (uint64_t)bindInfo.pBufferBinds[j].buffer, kVulkanObjectTypeBuffer)) 100883251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip = true; 100895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 100905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 100911344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis for (uint32_t j = 0; j < bindInfo.imageOpaqueBindCount; j++) { 100921344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis for (uint32_t k = 0; k < bindInfo.pImageOpaqueBinds[j].bindCount; k++) { 10093f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis auto sparse_binding = bindInfo.pImageOpaqueBinds[j].pBinds[k]; 10094f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis if (SetSparseMemBinding(dev_data, {sparse_binding.memory, sparse_binding.memoryOffset, sparse_binding.size}, 10095ece0e981ee4a5ad2572d146a89fc64d699d79f36Chris Forbes (uint64_t)bindInfo.pImageOpaqueBinds[j].image, kVulkanObjectTypeImage)) 100963251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip = true; 100975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 100985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 100991344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis for (uint32_t j = 0; j < bindInfo.imageBindCount; j++) { 101001344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis for (uint32_t k = 0; k < bindInfo.pImageBinds[j].bindCount; k++) { 10101f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis auto sparse_binding = bindInfo.pImageBinds[j].pBinds[k]; 10102f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis // TODO: This size is broken for non-opaque bindings, need to update to comprehend full sparse binding data 10103f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis VkDeviceSize size = sparse_binding.extent.depth * sparse_binding.extent.height * sparse_binding.extent.width * 4; 10104f19cf73769d6fc784ef4c3bf70b85739b4810693Tobin Ehlis if (SetSparseMemBinding(dev_data, {sparse_binding.memory, sparse_binding.memoryOffset, size}, 10105ece0e981ee4a5ad2572d146a89fc64d699d79f36Chris Forbes (uint64_t)bindInfo.pImageBinds[j].image, kVulkanObjectTypeImage)) 101063251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip = true; 101075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 101085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 101099867daedbf52debc77d6568162ee21e071699b80Chris Forbes 101109867daedbf52debc77d6568162ee21e071699b80Chris Forbes std::vector<SEMAPHORE_WAIT> semaphore_waits; 101119867daedbf52debc77d6568162ee21e071699b80Chris Forbes std::vector<VkSemaphore> semaphore_signals; 101121344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis for (uint32_t i = 0; i < bindInfo.waitSemaphoreCount; ++i) { 1011301a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes VkSemaphore semaphore = bindInfo.pWaitSemaphores[i]; 101149a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pSemaphore = GetSemaphoreNode(dev_data, semaphore); 1011501a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes if (pSemaphore) { 1011601a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes if (pSemaphore->signaled) { 101179867daedbf52debc77d6568162ee21e071699b80Chris Forbes if (pSemaphore->signaler.first != VK_NULL_HANDLE) { 101189867daedbf52debc77d6568162ee21e071699b80Chris Forbes semaphore_waits.push_back({semaphore, pSemaphore->signaler.first, pSemaphore->signaler.second}); 101199867daedbf52debc77d6568162ee21e071699b80Chris Forbes pSemaphore->in_use.fetch_add(1); 101209867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 101219867daedbf52debc77d6568162ee21e071699b80Chris Forbes pSemaphore->signaler.first = VK_NULL_HANDLE; 1012201a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes pSemaphore->signaled = false; 101231344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis } else { 101243251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT, 101253251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<const uint64_t &>(semaphore), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS", 101263251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkQueueBindSparse: Queue 0x%p is waiting on semaphore 0x%" PRIx64 101273251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski " that has no way to be signaled.", 101283251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski queue, reinterpret_cast<const uint64_t &>(semaphore)); 101295b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 101305b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 101315b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 101321344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis for (uint32_t i = 0; i < bindInfo.signalSemaphoreCount; ++i) { 1013301a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes VkSemaphore semaphore = bindInfo.pSignalSemaphores[i]; 101349a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pSemaphore = GetSemaphoreNode(dev_data, semaphore); 1013501a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes if (pSemaphore) { 1013601a48e41895b3951b297ff4245eff8f9c129ae20Chris Forbes if (pSemaphore->signaled) { 101373251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT, 101383251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<const uint64_t &>(semaphore), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS", 101393251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkQueueBindSparse: Queue 0x%p is signaling semaphore 0x%" PRIx64 101403251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski ", but that semaphore is already signaled.", 101413251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski queue, reinterpret_cast<const uint64_t &>(semaphore)); 10142bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski } else { 101439867daedbf52debc77d6568162ee21e071699b80Chris Forbes pSemaphore->signaler.first = queue; 101449867daedbf52debc77d6568162ee21e071699b80Chris Forbes pSemaphore->signaler.second = pQueue->seq + pQueue->submissions.size() + 1; 101459867daedbf52debc77d6568162ee21e071699b80Chris Forbes pSemaphore->signaled = true; 101469867daedbf52debc77d6568162ee21e071699b80Chris Forbes pSemaphore->in_use.fetch_add(1); 101479867daedbf52debc77d6568162ee21e071699b80Chris Forbes semaphore_signals.push_back(semaphore); 101489867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 101495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 101505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 101519867daedbf52debc77d6568162ee21e071699b80Chris Forbes 10152bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pQueue->submissions.emplace_back(std::vector<VkCommandBuffer>(), semaphore_waits, semaphore_signals, 101539867daedbf52debc77d6568162ee21e071699b80Chris Forbes bindIdx == bindInfoCount - 1 ? fence : VK_NULL_HANDLE); 101545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 101559867daedbf52debc77d6568162ee21e071699b80Chris Forbes 101569867daedbf52debc77d6568162ee21e071699b80Chris Forbes if (pFence && !bindInfoCount) { 101579867daedbf52debc77d6568162ee21e071699b80Chris Forbes // No work to do, just dropping a fence in the queue by itself. 10158bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pQueue->submissions.emplace_back(std::vector<VkCommandBuffer>(), std::vector<SEMAPHORE_WAIT>(), std::vector<VkSemaphore>(), 101599867daedbf52debc77d6568162ee21e071699b80Chris Forbes fence); 101609867daedbf52debc77d6568162ee21e071699b80Chris Forbes } 101619867daedbf52debc77d6568162ee21e071699b80Chris Forbes 10162b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 101635b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 101643251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) return dev_data->dispatch_table.QueueBindSparse(queue, bindInfoCount, pBindInfo, fence); 101655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 101665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 101675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 101685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1016989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL CreateSemaphore(VkDevice device, const VkSemaphoreCreateInfo *pCreateInfo, 1017089d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator, VkSemaphore *pSemaphore) { 1017156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 101724a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateSemaphore(device, pCreateInfo, pAllocator, pSemaphore); 101735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (result == VK_SUCCESS) { 10174b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 10175bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski SEMAPHORE_NODE *sNode = &dev_data->semaphoreMap[*pSemaphore]; 101769867daedbf52debc77d6568162ee21e071699b80Chris Forbes sNode->signaler.first = VK_NULL_HANDLE; 101779867daedbf52debc77d6568162ee21e071699b80Chris Forbes sNode->signaler.second = 0; 101781344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis sNode->signaled = false; 101795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 101805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 101815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 101825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10183bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateEvent(VkDevice device, const VkEventCreateInfo *pCreateInfo, 10184bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkEvent *pEvent) { 1018556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 101864a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.CreateEvent(device, pCreateInfo, pAllocator, pEvent); 101875b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (result == VK_SUCCESS) { 10188b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 101895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->eventMap[*pEvent].needsSignaled = false; 10190293ecfc5e69ed3978a8c04518166d828294870a4Tony Barbour dev_data->eventMap[*pEvent].write_in_use = 0; 101915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->eventMap[*pEvent].stageMask = VkPipelineStageFlags(0); 101925b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 101935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 101945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 101955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 101969ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinskistatic bool PreCallValidateCreateSwapchainKHR(layer_data *dev_data, const char *func_name, 101979ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski VkSwapchainCreateInfoKHR const *pCreateInfo, SURFACE_STATE *surface_state, 101989ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski SWAPCHAIN_NODE *old_swapchain_state) { 10199d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes auto most_recent_swapchain = surface_state->swapchain ? surface_state->swapchain : surface_state->old_swapchain; 10200d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes 102014bd5f453535de3d3423ff1f9995b4acb15f791d2Chris Forbes // TODO: revisit this. some of these rules are being relaxed. 10202d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes if (most_recent_swapchain != old_swapchain_state || (surface_state->old_swapchain && surface_state->swapchain)) { 10203d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 10204d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes reinterpret_cast<uint64_t>(dev_data->device), __LINE__, DRAWSTATE_SWAPCHAIN_ALREADY_EXISTS, "DS", 102059ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s: surface has an existing swapchain other than oldSwapchain", func_name)) 10206d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes return true; 10207d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes } 10208d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes if (old_swapchain_state && old_swapchain_state->createInfo.surface != pCreateInfo->surface) { 10209d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 10210d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes reinterpret_cast<uint64_t const &>(pCreateInfo->oldSwapchain), __LINE__, DRAWSTATE_SWAPCHAIN_WRONG_SURFACE, 102119ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "DS", "%s: pCreateInfo->oldSwapchain's surface is not pCreateInfo->surface", func_name)) 10212d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes return true; 10213d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes } 102149a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto physical_device_state = GetPhysicalDeviceState(dev_data->instance_data, dev_data->physical_device); 102157de258f87ca1192db116a66b209253793d276ebcChris Forbes if (physical_device_state->vkGetPhysicalDeviceSurfaceCapabilitiesKHRState == UNCALLED) { 102167de258f87ca1192db116a66b209253793d276ebcChris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 102177de258f87ca1192db116a66b209253793d276ebcChris Forbes reinterpret_cast<uint64_t>(dev_data->physical_device), __LINE__, DRAWSTATE_SWAPCHAIN_CREATE_BEFORE_QUERY, "DS", 102189ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s: surface capabilities not retrieved for this physical device", func_name)) 102197de258f87ca1192db116a66b209253793d276ebcChris Forbes return true; 10220cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else { // have valid capabilities 102215c99b4daed164798f307244c9bde17b4f66014fbChris Forbes auto &capabilities = physical_device_state->surfaceCapabilities; 102229ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // Validate pCreateInfo->minImageCount against VkSurfaceCapabilitiesKHR::{min|max}ImageCount: 102232fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen if (pCreateInfo->minImageCount < capabilities.minImageCount) { 102242fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 102252fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t>(dev_data->device), __LINE__, VALIDATION_ERROR_02331, "DS", 102269ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s called with minImageCount = %d, which is outside the bounds returned " 102272fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen "by vkGetPhysicalDeviceSurfaceCapabilitiesKHR() (i.e. minImageCount = %d, maxImageCount = %d). %s", 102289ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski func_name, pCreateInfo->minImageCount, capabilities.minImageCount, capabilities.maxImageCount, 102292fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen validation_error_map[VALIDATION_ERROR_02331])) 102302fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen return true; 102312fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen } 102322fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen 102332fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen if ((capabilities.maxImageCount > 0) && (pCreateInfo->minImageCount > capabilities.maxImageCount)) { 102345c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 102352fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t>(dev_data->device), __LINE__, VALIDATION_ERROR_02332, "DS", 102369ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s called with minImageCount = %d, which is outside the bounds returned " 102372fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen "by vkGetPhysicalDeviceSurfaceCapabilitiesKHR() (i.e. minImageCount = %d, maxImageCount = %d). %s", 102389ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski func_name, pCreateInfo->minImageCount, capabilities.minImageCount, capabilities.maxImageCount, 102392fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen validation_error_map[VALIDATION_ERROR_02332])) 102405c99b4daed164798f307244c9bde17b4f66014fbChris Forbes return true; 102415c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 102422fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen 102439ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // Validate pCreateInfo->imageExtent against VkSurfaceCapabilitiesKHR::{current|min|max}ImageExtent: 102442e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill if ((capabilities.currentExtent.width == kSurfaceSizeFromSwapchain) && 102452e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill ((pCreateInfo->imageExtent.width < capabilities.minImageExtent.width) || 102462e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill (pCreateInfo->imageExtent.width > capabilities.maxImageExtent.width) || 102472e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill (pCreateInfo->imageExtent.height < capabilities.minImageExtent.height) || 102482e935bbc6cacaff38c073f86594a1b56d1f8a800Jamie Madill (pCreateInfo->imageExtent.height > capabilities.maxImageExtent.height))) { 102495c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 102502fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t>(dev_data->device), __LINE__, VALIDATION_ERROR_02334, "DS", 102519ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s called with imageExtent = (%d,%d), which is outside the bounds returned by " 102529ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "vkGetPhysicalDeviceSurfaceCapabilitiesKHR(): currentExtent = (%d,%d), minImageExtent = (%d,%d), " 102539ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "maxImageExtent = (%d,%d). %s", 102549ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski func_name, pCreateInfo->imageExtent.width, pCreateInfo->imageExtent.height, 102559ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski capabilities.currentExtent.width, capabilities.currentExtent.height, capabilities.minImageExtent.width, 102569ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski capabilities.minImageExtent.height, capabilities.maxImageExtent.width, capabilities.maxImageExtent.height, 102572fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen validation_error_map[VALIDATION_ERROR_02334])) 102585c99b4daed164798f307244c9bde17b4f66014fbChris Forbes return true; 102595c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 102609ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // pCreateInfo->preTransform should have exactly one bit set, and that bit must also be set in 102619ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // VkSurfaceCapabilitiesKHR::supportedTransforms. 102625c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (!pCreateInfo->preTransform || (pCreateInfo->preTransform & (pCreateInfo->preTransform - 1)) || 102635c99b4daed164798f307244c9bde17b4f66014fbChris Forbes !(pCreateInfo->preTransform & capabilities.supportedTransforms)) { 102649ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // This is an error situation; one for which we'd like to give the developer a helpful, multi-line error message. Build 102659ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // it up a little at a time, and then log it: 102665c99b4daed164798f307244c9bde17b4f66014fbChris Forbes std::string errorString = ""; 102675c99b4daed164798f307244c9bde17b4f66014fbChris Forbes char str[1024]; 102685c99b4daed164798f307244c9bde17b4f66014fbChris Forbes // Here's the first part of the message: 102699ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski sprintf(str, "%s called with a non-supported pCreateInfo->preTransform (i.e. %s). Supported values are:\n", func_name, 102705c99b4daed164798f307244c9bde17b4f66014fbChris Forbes string_VkSurfaceTransformFlagBitsKHR(pCreateInfo->preTransform)); 102715c99b4daed164798f307244c9bde17b4f66014fbChris Forbes errorString += str; 102725c99b4daed164798f307244c9bde17b4f66014fbChris Forbes for (int i = 0; i < 32; i++) { 102735c99b4daed164798f307244c9bde17b4f66014fbChris Forbes // Build up the rest of the message: 102745c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if ((1 << i) & capabilities.supportedTransforms) { 102755c99b4daed164798f307244c9bde17b4f66014fbChris Forbes const char *newStr = string_VkSurfaceTransformFlagBitsKHR((VkSurfaceTransformFlagBitsKHR)(1 << i)); 102765c99b4daed164798f307244c9bde17b4f66014fbChris Forbes sprintf(str, " %s\n", newStr); 102775c99b4daed164798f307244c9bde17b4f66014fbChris Forbes errorString += str; 102785c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 102795c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 102805c99b4daed164798f307244c9bde17b4f66014fbChris Forbes // Log the message that we've built up: 102815c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 102822fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t &>(dev_data->device), __LINE__, VALIDATION_ERROR_02339, "DS", "%s. %s", 102832fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen errorString.c_str(), validation_error_map[VALIDATION_ERROR_02339])) 102845c99b4daed164798f307244c9bde17b4f66014fbChris Forbes return true; 102855c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 102867b0d28d116977b91892f354e002edd760bdb86cbChris Forbes 102879ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // pCreateInfo->compositeAlpha should have exactly one bit set, and that bit must also be set in 102889ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // VkSurfaceCapabilitiesKHR::supportedCompositeAlpha 102895c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (!pCreateInfo->compositeAlpha || (pCreateInfo->compositeAlpha & (pCreateInfo->compositeAlpha - 1)) || 102905c99b4daed164798f307244c9bde17b4f66014fbChris Forbes !((pCreateInfo->compositeAlpha) & capabilities.supportedCompositeAlpha)) { 102919ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // This is an error situation; one for which we'd like to give the developer a helpful, multi-line error message. Build 102929ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // it up a little at a time, and then log it: 102935c99b4daed164798f307244c9bde17b4f66014fbChris Forbes std::string errorString = ""; 102945c99b4daed164798f307244c9bde17b4f66014fbChris Forbes char str[1024]; 102955c99b4daed164798f307244c9bde17b4f66014fbChris Forbes // Here's the first part of the message: 102969ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski sprintf(str, "%s called with a non-supported pCreateInfo->compositeAlpha (i.e. %s). Supported values are:\n", 102979ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski func_name, string_VkCompositeAlphaFlagBitsKHR(pCreateInfo->compositeAlpha)); 102985c99b4daed164798f307244c9bde17b4f66014fbChris Forbes errorString += str; 102995c99b4daed164798f307244c9bde17b4f66014fbChris Forbes for (int i = 0; i < 32; i++) { 103005c99b4daed164798f307244c9bde17b4f66014fbChris Forbes // Build up the rest of the message: 103015c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if ((1 << i) & capabilities.supportedCompositeAlpha) { 103025c99b4daed164798f307244c9bde17b4f66014fbChris Forbes const char *newStr = string_VkCompositeAlphaFlagBitsKHR((VkCompositeAlphaFlagBitsKHR)(1 << i)); 103035c99b4daed164798f307244c9bde17b4f66014fbChris Forbes sprintf(str, " %s\n", newStr); 103045c99b4daed164798f307244c9bde17b4f66014fbChris Forbes errorString += str; 103055c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 103065c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 103075c99b4daed164798f307244c9bde17b4f66014fbChris Forbes // Log the message that we've built up: 103085c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 103092fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t &>(dev_data->device), __LINE__, VALIDATION_ERROR_02340, "DS", "%s. %s", 103102fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen errorString.c_str(), validation_error_map[VALIDATION_ERROR_02340])) 103115c99b4daed164798f307244c9bde17b4f66014fbChris Forbes return true; 103125c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 103139ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // Validate pCreateInfo->imageArrayLayers against VkSurfaceCapabilitiesKHR::maxImageArrayLayers: 103145c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if ((pCreateInfo->imageArrayLayers < 1) || (pCreateInfo->imageArrayLayers > capabilities.maxImageArrayLayers)) { 103155c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 103162fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t>(dev_data->device), __LINE__, VALIDATION_ERROR_02335, "DS", 103179ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s called with a non-supported imageArrayLayers (i.e. %d). Minimum value is 1, maximum value is %d. %s", 103189ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski func_name, pCreateInfo->imageArrayLayers, capabilities.maxImageArrayLayers, 103192fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen validation_error_map[VALIDATION_ERROR_02335])) 103205c99b4daed164798f307244c9bde17b4f66014fbChris Forbes return true; 103215c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 103229ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // Validate pCreateInfo->imageUsage against VkSurfaceCapabilitiesKHR::supportedUsageFlags: 103235c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (pCreateInfo->imageUsage != (pCreateInfo->imageUsage & capabilities.supportedUsageFlags)) { 103245c99b4daed164798f307244c9bde17b4f66014fbChris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 103252fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t>(dev_data->device), __LINE__, VALIDATION_ERROR_02336, "DS", 103269ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s called with a non-supported pCreateInfo->imageUsage (i.e. 0x%08x). Supported flag bits are 0x%08x. %s", 103279ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski func_name, pCreateInfo->imageUsage, capabilities.supportedUsageFlags, 103289ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski validation_error_map[VALIDATION_ERROR_02336])) 103295c99b4daed164798f307244c9bde17b4f66014fbChris Forbes return true; 103305c99b4daed164798f307244c9bde17b4f66014fbChris Forbes } 103317de258f87ca1192db116a66b209253793d276ebcChris Forbes } 10332d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes 103339ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // Validate pCreateInfo values with the results of vkGetPhysicalDeviceSurfaceFormatsKHR(): 103345faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (physical_device_state->vkGetPhysicalDeviceSurfaceFormatsKHRState != QUERY_DETAILS) { 103355faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 103365faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes reinterpret_cast<uint64_t>(dev_data->device), __LINE__, DRAWSTATE_SWAPCHAIN_CREATE_BEFORE_QUERY, "DS", 103379ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s called before calling vkGetPhysicalDeviceSurfaceFormatsKHR().", func_name)) 103385faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes return true; 103395faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } else { 103409ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // Validate pCreateInfo->imageFormat against VkSurfaceFormatKHR::format: 103415faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes bool foundFormat = false; 103425faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes bool foundColorSpace = false; 103435faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes bool foundMatch = false; 103445faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes for (auto const &format : physical_device_state->surface_formats) { 103455faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (pCreateInfo->imageFormat == format.format) { 103469ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // Validate pCreateInfo->imageColorSpace against VkSurfaceFormatKHR::colorSpace: 103475faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes foundFormat = true; 103485faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (pCreateInfo->imageColorSpace == format.colorSpace) { 103495faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes foundMatch = true; 103505faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes break; 103515faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 103525faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } else { 103535faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (pCreateInfo->imageColorSpace == format.colorSpace) { 103545faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes foundColorSpace = true; 103555faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 103565faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 103575faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 103585faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (!foundMatch) { 103595faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (!foundFormat) { 103605faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 103612fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t>(dev_data->device), __LINE__, VALIDATION_ERROR_02333, "DS", 10362bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "%s called with a non-supported pCreateInfo->imageFormat (i.e. %d). %s", func_name, 10363bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pCreateInfo->imageFormat, validation_error_map[VALIDATION_ERROR_02333])) 103642fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen return true; 103652fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen } 103662fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen if (!foundColorSpace) { 103672fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 103682fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t>(dev_data->device), __LINE__, VALIDATION_ERROR_02333, "DS", 10369bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "%s called with a non-supported pCreateInfo->imageColorSpace (i.e. %d). %s", func_name, 10370bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pCreateInfo->imageColorSpace, validation_error_map[VALIDATION_ERROR_02333])) 103715faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes return true; 103725faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 103735faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 103745faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 103755faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes 103769ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // Validate pCreateInfo values with the results of vkGetPhysicalDeviceSurfacePresentModesKHR(): 103779e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (physical_device_state->vkGetPhysicalDeviceSurfacePresentModesKHRState != QUERY_DETAILS) { 1037825002b75574f762c62b1a00a595bab04ebb25452Mark Lobodzinski // FIFO is required to always be supported 103799e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (pCreateInfo->presentMode != VK_PRESENT_MODE_FIFO_KHR) { 103809e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 103819ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski reinterpret_cast<uint64_t>(dev_data->device), __LINE__, DRAWSTATE_SWAPCHAIN_CREATE_BEFORE_QUERY, "DS", 103829ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s called before calling vkGetPhysicalDeviceSurfacePresentModesKHR().", func_name)) 103839e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes return true; 103849e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 103859e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } else { 103869ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski // Validate pCreateInfo->presentMode against vkGetPhysicalDeviceSurfacePresentModesKHR(): 10387bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski bool foundMatch = std::find(physical_device_state->present_modes.begin(), physical_device_state->present_modes.end(), 103889e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes pCreateInfo->presentMode) != physical_device_state->present_modes.end(); 103899e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (!foundMatch) { 103909e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 103912fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t>(dev_data->device), __LINE__, VALIDATION_ERROR_02341, "DS", 103929ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski "%s called with a non-supported presentMode (i.e. %s). %s", func_name, 103932fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen string_VkPresentModeKHR(pCreateInfo->presentMode), validation_error_map[VALIDATION_ERROR_02341])) 103949e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes return true; 103959e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 103969e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 103979e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes 10398d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes return false; 10399d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes} 10400d3b3114fb37a32af2ba563f784da54a877492b23Chris Forbes 10401261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinskistatic void PostCallRecordCreateSwapchainKHR(layer_data *dev_data, VkResult result, const VkSwapchainCreateInfoKHR *pCreateInfo, 10402261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski VkSwapchainKHR *pSwapchain, SURFACE_STATE *surface_state, 10403261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski SWAPCHAIN_NODE *old_swapchain_state) { 104045b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == result) { 10405b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 10406ddc5201048319558ce66701163a4546ee957af19Chris Forbes auto swapchain_state = unique_ptr<SWAPCHAIN_NODE>(new SWAPCHAIN_NODE(pCreateInfo, *pSwapchain)); 10407ddc5201048319558ce66701163a4546ee957af19Chris Forbes surface_state->swapchain = swapchain_state.get(); 10408ddc5201048319558ce66701163a4546ee957af19Chris Forbes dev_data->device_extensions.swapchainMap[*pSwapchain] = std::move(swapchain_state); 10409ddc5201048319558ce66701163a4546ee957af19Chris Forbes } else { 10410ddc5201048319558ce66701163a4546ee957af19Chris Forbes surface_state->swapchain = nullptr; 104115b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 10412ddc5201048319558ce66701163a4546ee957af19Chris Forbes // Spec requires that even if CreateSwapchainKHR fails, oldSwapchain behaves as replaced. 104135b5488456e5afa0487f95b805a2aba59b13d69f4Chris Forbes if (old_swapchain_state) { 104145b5488456e5afa0487f95b805a2aba59b13d69f4Chris Forbes old_swapchain_state->replaced = true; 104155b5488456e5afa0487f95b805a2aba59b13d69f4Chris Forbes } 10416ddc5201048319558ce66701163a4546ee957af19Chris Forbes surface_state->old_swapchain = old_swapchain_state; 10417261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski return; 10418261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski} 10419261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski 10420261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo, 10421261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchain) { 1042256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 104239a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto surface_state = GetSurfaceState(dev_data->instance_data, pCreateInfo->surface); 104249a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto old_swapchain_state = GetSwapchainNode(dev_data, pCreateInfo->oldSwapchain); 10425261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski 104269ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski if (PreCallValidateCreateSwapchainKHR(dev_data, "vkCreateSwapChainKHR()", pCreateInfo, surface_state, old_swapchain_state)) { 10427261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski return VK_ERROR_VALIDATION_FAILED_EXT; 10428261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski } 10429261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski 10430261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski VkResult result = dev_data->dispatch_table.CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain); 10431261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski 10432261dc1ef7a86b64cce92a6811bf80ee4ba364a48Mark Lobodzinski PostCallRecordCreateSwapchainKHR(dev_data, result, pCreateInfo, pSwapchain, surface_state, old_swapchain_state); 10433ddc5201048319558ce66701163a4546ee957af19Chris Forbes 104345b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 104355b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 104365b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10437bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks *pAllocator) { 1043856e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 104393251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 104405b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10441b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 104429a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto swapchain_data = GetSwapchainNode(dev_data, swapchain); 10443b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis if (swapchain_data) { 10444b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis if (swapchain_data->images.size() > 0) { 10445b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis for (auto swapchain_image : swapchain_data->images) { 104465b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto image_sub = dev_data->imageSubresourceMap.find(swapchain_image); 104475b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (image_sub != dev_data->imageSubresourceMap.end()) { 104485b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (auto imgsubpair : image_sub->second) { 104495b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis auto image_item = dev_data->imageLayoutMap.find(imgsubpair); 104505b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (image_item != dev_data->imageLayoutMap.end()) { 104515b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->imageLayoutMap.erase(image_item); 104525b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 104535b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 104545b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->imageSubresourceMap.erase(image_sub); 104555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 104563251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip = ClearMemoryObjectBindings(dev_data, (uint64_t)swapchain_image, kVulkanObjectTypeSwapchainKHR); 1045794c53c062f0ccc70ef0ada8e98edc90eadc4cb45Tobin Ehlis dev_data->imageMap.erase(swapchain_image); 104585b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 104595b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 10460ddc5201048319558ce66701163a4546ee957af19Chris Forbes 104619a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto surface_state = GetSurfaceState(dev_data->instance_data, swapchain_data->createInfo.surface); 10462ddc5201048319558ce66701163a4546ee957af19Chris Forbes if (surface_state) { 10463cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (surface_state->swapchain == swapchain_data) surface_state->swapchain = nullptr; 10464cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (surface_state->old_swapchain == swapchain_data) surface_state->old_swapchain = nullptr; 10465ddc5201048319558ce66701163a4546ee957af19Chris Forbes } 10466ddc5201048319558ce66701163a4546ee957af19Chris Forbes 104675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->device_extensions.swapchainMap.erase(swapchain); 104685b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 10469b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 104703251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) dev_data->dispatch_table.DestroySwapchainKHR(device, swapchain, pAllocator); 104715b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 104725b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10473bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL GetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t *pCount, 10474bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkImage *pSwapchainImages) { 1047556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 104764a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.GetSwapchainImagesKHR(device, swapchain, pCount, pSwapchainImages); 104775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 104785b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (result == VK_SUCCESS && pSwapchainImages != NULL) { 104795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // This should never happen and is checked by param checker. 10480cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!pCount) return result; 10481b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 104825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis const size_t count = *pCount; 104839a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto swapchain_node = GetSwapchainNode(dev_data, swapchain); 10484b110cb87b9478586719d7f7dc769b350857366baTobin Ehlis if (swapchain_node && !swapchain_node->images.empty()) { 104850801763633180d277d26a90343464bd11646056fTobin Ehlis // TODO : Not sure I like the memcmp here, but it works 104860801763633180d277d26a90343464bd11646056fTobin Ehlis const bool mismatch = (swapchain_node->images.size() != count || 104870801763633180d277d26a90343464bd11646056fTobin Ehlis memcmp(&swapchain_node->images[0], pSwapchainImages, sizeof(swapchain_node->images[0]) * count)); 104885b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (mismatch) { 104895b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis // TODO: Verify against Valid Usage section of extension 104905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 104915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (uint64_t)swapchain, __LINE__, MEMTRACK_NONE, "SWAP_CHAIN", 10492414e9a4117b500eac650d8b8f01a6e1b22d05aaeMark Mueller "vkGetSwapchainInfoKHR(0x%" PRIx64 104935b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis ", VK_SWAP_CHAIN_INFO_TYPE_PERSISTENT_IMAGES_KHR) returned mismatching data", 104945b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis (uint64_t)(swapchain)); 104955b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 104965b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 104975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis for (uint32_t i = 0; i < *pCount; ++i) { 104985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis IMAGE_LAYOUT_NODE image_layout_node; 104995b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis image_layout_node.layout = VK_IMAGE_LAYOUT_UNDEFINED; 105005b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis image_layout_node.format = swapchain_node->createInfo.imageFormat; 105016d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis // Add imageMap entries for each swapchain image 105026d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis VkImageCreateInfo image_ci = {}; 10503eb6ea7587bdc06e98a89398f113fe3610d270dcbChris Forbes image_ci.flags = 0; 10504eb6ea7587bdc06e98a89398f113fe3610d270dcbChris Forbes image_ci.imageType = VK_IMAGE_TYPE_2D; 105056d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis image_ci.format = swapchain_node->createInfo.imageFormat; 105066d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis image_ci.extent.width = swapchain_node->createInfo.imageExtent.width; 105076d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis image_ci.extent.height = swapchain_node->createInfo.imageExtent.height; 10508d1a9776c1a22ec99a3ef0dd44e7f85a78a04d1edTony Barbour image_ci.extent.depth = 1; 10509eb6ea7587bdc06e98a89398f113fe3610d270dcbChris Forbes image_ci.mipLevels = 1; 10510eb6ea7587bdc06e98a89398f113fe3610d270dcbChris Forbes image_ci.arrayLayers = swapchain_node->createInfo.imageArrayLayers; 10511eb6ea7587bdc06e98a89398f113fe3610d270dcbChris Forbes image_ci.samples = VK_SAMPLE_COUNT_1_BIT; 10512eb6ea7587bdc06e98a89398f113fe3610d270dcbChris Forbes image_ci.tiling = VK_IMAGE_TILING_OPTIMAL; 10513eb6ea7587bdc06e98a89398f113fe3610d270dcbChris Forbes image_ci.usage = swapchain_node->createInfo.imageUsage; 105146d1373829eded68f6e080ff2c33e03231360ed57Tobin Ehlis image_ci.sharingMode = swapchain_node->createInfo.imageSharingMode; 105151facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis dev_data->imageMap[pSwapchainImages[i]] = unique_ptr<IMAGE_STATE>(new IMAGE_STATE(pSwapchainImages[i], &image_ci)); 105161facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis auto &image_state = dev_data->imageMap[pSwapchainImages[i]]; 105171facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis image_state->valid = false; 10518e46491ee6f16b9d29e68914fc6522aba2fde0ad4Tobin Ehlis image_state->binding.mem = MEMTRACKER_SWAP_CHAIN_IMAGE_KEY; 105195b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis swapchain_node->images.push_back(pSwapchainImages[i]); 105205b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis ImageSubresourcePair subpair = {pSwapchainImages[i], false, VkImageSubresource()}; 105215b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->imageSubresourceMap[pSwapchainImages[i]].push_back(subpair); 105225b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->imageLayoutMap[subpair] = image_layout_node; 105235b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis dev_data->device_extensions.imageToSwapchainMap[pSwapchainImages[i]] = swapchain; 105245b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 105255b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 105265b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 105275b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 105285b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1052989d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo) { 1053056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map); 105313251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 105325b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 105336c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes std::lock_guard<std::mutex> lock(global_lock); 105349a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto queue_state = GetQueueState(dev_data, queue); 105351671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes 105366c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes for (uint32_t i = 0; i < pPresentInfo->waitSemaphoreCount; ++i) { 105379a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pSemaphore = GetSemaphoreNode(dev_data, pPresentInfo->pWaitSemaphores[i]); 105386c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes if (pSemaphore && !pSemaphore->signaled) { 105393251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, 105403251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS", 105413251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Queue 0x%p is waiting on semaphore 0x%" PRIx64 " that has no way to be signaled.", queue, 105423251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<const uint64_t &>(pPresentInfo->pWaitSemaphores[i])); 105435b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 105446c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes } 10545249eb117f85f5e0f3f3a83a2bf297893e0d054ceTobin Ehlis 105466c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes for (uint32_t i = 0; i < pPresentInfo->swapchainCount; ++i) { 105479a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto swapchain_data = GetSwapchainNode(dev_data, pPresentInfo->pSwapchains[i]); 10548a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes if (swapchain_data) { 10549a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes if (pPresentInfo->pImageIndices[i] >= swapchain_data->images.size()) { 105503251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg( 10551bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 10552bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski reinterpret_cast<uint64_t const &>(pPresentInfo->pSwapchains[i]), __LINE__, DRAWSTATE_SWAPCHAIN_INVALID_IMAGE, 10553bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "DS", "vkQueuePresentKHR: Swapchain image index too large (%u). There are only %u images in this swapchain.", 10554bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pPresentInfo->pImageIndices[i], (uint32_t)swapchain_data->images.size()); 10555bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski } else { 10556a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes auto image = swapchain_data->images[pPresentInfo->pImageIndices[i]]; 105579a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_state = GetImageState(dev_data, image); 105583251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateImageMemoryIsValid(dev_data, image_state, "vkQueuePresentKHR()"); 10559a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes 105601facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis if (!image_state->acquired) { 105613251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg( 10562bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 10563bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski reinterpret_cast<uint64_t const &>(pPresentInfo->pSwapchains[i]), __LINE__, 10564bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski DRAWSTATE_SWAPCHAIN_IMAGE_NOT_ACQUIRED, "DS", 10565bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski "vkQueuePresentKHR: Swapchain image index %u has not been acquired.", pPresentInfo->pImageIndices[i]); 10566a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes } 10567a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes 10568a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes vector<VkImageLayout> layouts; 10569a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes if (FindLayouts(dev_data, image, layouts)) { 10570a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes for (auto layout : layouts) { 10571a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes if (layout != VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) { 105723251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 105732fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT, 105742fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen reinterpret_cast<uint64_t &>(queue), __LINE__, VALIDATION_ERROR_01964, "DS", 105752fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen "Images passed to present must be in layout " 105762fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen "VK_IMAGE_LAYOUT_PRESENT_SRC_KHR but is in %s. %s", 105772fbc1a61dff1781368a0c592c25985abb46e4891Mike Weiblen string_VkImageLayout(layout), validation_error_map[VALIDATION_ERROR_01964]); 10578a96bccebcf27add1b38bfe46c541e1484d7b4d88Chris Forbes } 105795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 105805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 105815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 105821671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes 105831671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes // All physical devices and queue families are required to be able 105841671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes // to present to any native window on Android; require the 105851671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes // application to have established support on any other platform. 105861671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes if (!dev_data->instance_data->androidSurfaceExtensionEnabled) { 105879a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto surface_state = GetSurfaceState(dev_data->instance_data, swapchain_data->createInfo.surface); 105881671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes auto support_it = surface_state->gpu_queue_support.find({dev_data->physical_device, queue_state->queueFamilyIndex}); 105891671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes 105901671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes if (support_it == surface_state->gpu_queue_support.end()) { 105913251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 105921671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 105931671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes reinterpret_cast<uint64_t const &>(pPresentInfo->pSwapchains[i]), __LINE__, 10594cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski DRAWSTATE_SWAPCHAIN_UNSUPPORTED_QUEUE, "DS", 10595cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkQueuePresentKHR: Presenting image without calling " 10596cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkGetPhysicalDeviceSurfaceSupportKHR"); 105971671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes } else if (!support_it->second) { 105983251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg( 10599cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 10600cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski reinterpret_cast<uint64_t const &>(pPresentInfo->pSwapchains[i]), __LINE__, VALIDATION_ERROR_01961, "DS", 10601cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkQueuePresentKHR: Presenting image on queue that cannot " 10602cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "present to this surface. %s", 10603cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski validation_error_map[VALIDATION_ERROR_01961]); 106041671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes } 106051671dfbfc53aa19dcf76d71c2dd1f8f2c4879174Chris Forbes } 106065b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 106075b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 10608c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis if (pPresentInfo && pPresentInfo->pNext) { 10609c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis // Verify ext struct 10610c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis struct std_header { 10611c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis VkStructureType sType; 10612c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis const void *pNext; 10613c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis }; 10614c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis std_header *pnext = (std_header *)pPresentInfo->pNext; 10615c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis while (pnext) { 10616c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis if (VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR == pnext->sType) { 10617c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis VkPresentRegionsKHR *present_regions = (VkPresentRegionsKHR *)pnext; 10618c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis for (uint32_t i = 0; i < present_regions->swapchainCount; ++i) { 10619c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis auto swapchain_data = GetSwapchainNode(dev_data, pPresentInfo->pSwapchains[i]); 10620c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis assert(swapchain_data); 10621c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis VkPresentRegionKHR region = present_regions->pRegions[i]; 10622c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis for (uint32_t j = 0; j < region.rectangleCount; ++j) { 10623c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis VkRectLayerKHR rect = region.pRectangles[j]; 10624c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis // TODO: Need to update these errors to their unique error ids when available 10625c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis if ((rect.offset.x + rect.extent.width) > swapchain_data->createInfo.imageExtent.width) { 106263251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 106273251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 106283251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t const &>(pPresentInfo->pSwapchains[i]), __LINE__, 106293251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski DRAWSTATE_SWAPCHAIN_INVALID_IMAGE, "DS", 106303251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkQueuePresentKHR(): For VkPresentRegionKHR down pNext " 106313251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "chain, pRegion[%i].pRectangles[%i], the sum of offset.x " 106323251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "(%i) and extent.width (%i) is greater than the " 106333251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "corresponding swapchain's imageExtent.width (%i).", 106343251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski i, j, rect.offset.x, rect.extent.width, swapchain_data->createInfo.imageExtent.width); 10635c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis } 10636c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis if ((rect.offset.y + rect.extent.height) > swapchain_data->createInfo.imageExtent.height) { 106373251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, 106383251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 106393251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t const &>(pPresentInfo->pSwapchains[i]), __LINE__, 106403251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski DRAWSTATE_SWAPCHAIN_INVALID_IMAGE, "DS", 106413251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkQueuePresentKHR(): For VkPresentRegionKHR down pNext " 106423251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "chain, pRegion[%i].pRectangles[%i], the sum of offset.y " 106433251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "(%i) and extent.height (%i) is greater than the " 106443251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "corresponding swapchain's imageExtent.height (%i).", 106453251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski i, j, rect.offset.y, rect.extent.height, swapchain_data->createInfo.imageExtent.height); 10646c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis } 10647c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis if (rect.layer > swapchain_data->createInfo.imageArrayLayers) { 106483251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg( 10649c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 10650c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis reinterpret_cast<uint64_t const &>(pPresentInfo->pSwapchains[i]), __LINE__, 10651c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis DRAWSTATE_SWAPCHAIN_INVALID_IMAGE, "DS", 10652c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis "vkQueuePresentKHR(): For VkPresentRegionKHR down pNext chain, pRegion[%i].pRectangles[%i], the " 10653c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis "layer (%i) is greater than the corresponding swapchain's imageArrayLayers (%i).", 10654c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis i, j, rect.layer, swapchain_data->createInfo.imageArrayLayers); 10655c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis } 10656c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis } 10657c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis } 106585f5e4095d630df9003597a928c86502e3fc83176Tobin Ehlis } else if (VK_STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE == pnext->sType) { 106595f5e4095d630df9003597a928c86502e3fc83176Tobin Ehlis VkPresentTimesInfoGOOGLE *present_times_info = (VkPresentTimesInfoGOOGLE *)pnext; 106605f5e4095d630df9003597a928c86502e3fc83176Tobin Ehlis if (pPresentInfo->swapchainCount != present_times_info->swapchainCount) { 106615f5e4095d630df9003597a928c86502e3fc83176Tobin Ehlis skip |= 106625f5e4095d630df9003597a928c86502e3fc83176Tobin Ehlis log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 106635f5e4095d630df9003597a928c86502e3fc83176Tobin Ehlis reinterpret_cast<uint64_t const &>(pPresentInfo->pSwapchains[0]), __LINE__, 106645f5e4095d630df9003597a928c86502e3fc83176Tobin Ehlis 106655f5e4095d630df9003597a928c86502e3fc83176Tobin Ehlis VALIDATION_ERROR_03214, "DS", 106665f5e4095d630df9003597a928c86502e3fc83176Tobin Ehlis "vkQueuePresentKHR(): VkPresentTimesInfoGOOGLE.swapchainCount is %i but " 106675f5e4095d630df9003597a928c86502e3fc83176Tobin Ehlis "pPresentInfo->swapchainCount is %i. For VkPresentTimesInfoGOOGLE down pNext " 106685f5e4095d630df9003597a928c86502e3fc83176Tobin Ehlis "chain of VkPresentInfoKHR, VkPresentTimesInfoGOOGLE.swapchainCount " 106695f5e4095d630df9003597a928c86502e3fc83176Tobin Ehlis "must equal VkPresentInfoKHR.swapchainCount.", 106705f5e4095d630df9003597a928c86502e3fc83176Tobin Ehlis present_times_info->swapchainCount, pPresentInfo->swapchainCount); 106715f5e4095d630df9003597a928c86502e3fc83176Tobin Ehlis } 10672c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis } 10673c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis pnext = (std_header *)pnext->pNext; 10674c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis } 10675c78bb8f84551ddfb3802d18c678500e26e4116cbTobin Ehlis } 106765b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 106773251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (skip) { 106786c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes return VK_ERROR_VALIDATION_FAILED_EXT; 106796c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes } 106806c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes 106814a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.QueuePresentKHR(queue, pPresentInfo); 106826c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes 106836c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes if (result != VK_ERROR_VALIDATION_FAILED_EXT) { 106846c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes // Semaphore waits occur before error generation, if the call reached 106856c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes // the ICD. (Confirm?) 106866c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes for (uint32_t i = 0; i < pPresentInfo->waitSemaphoreCount; ++i) { 106879a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pSemaphore = GetSemaphoreNode(dev_data, pPresentInfo->pWaitSemaphores[i]); 106889867daedbf52debc77d6568162ee21e071699b80Chris Forbes if (pSemaphore) { 106899867daedbf52debc77d6568162ee21e071699b80Chris Forbes pSemaphore->signaler.first = VK_NULL_HANDLE; 106906c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes pSemaphore->signaled = false; 106916c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes } 106926c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes } 106939867daedbf52debc77d6568162ee21e071699b80Chris Forbes 10694220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes for (uint32_t i = 0; i < pPresentInfo->swapchainCount; ++i) { 10695220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes // Note: this is imperfect, in that we can get confused about what 10696220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes // did or didn't succeed-- but if the app does that, it's confused 10697220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes // itself just as much. 10698220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes auto local_result = pPresentInfo->pResults ? pPresentInfo->pResults[i] : result; 10699220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes 10700cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (local_result != VK_SUCCESS && local_result != VK_SUBOPTIMAL_KHR) continue; // this present didn't actually happen. 10701220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes 10702220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes // Mark the image as having been released to the WSI 107039a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto swapchain_data = GetSwapchainNode(dev_data, pPresentInfo->pSwapchains[i]); 10704220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes auto image = swapchain_data->images[pPresentInfo->pImageIndices[i]]; 107059a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_state = GetImageState(dev_data, image); 107061facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis image_state->acquired = false; 10707220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes } 10708220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes 107099867daedbf52debc77d6568162ee21e071699b80Chris Forbes // Note: even though presentation is directed to a queue, there is no 107109867daedbf52debc77d6568162ee21e071699b80Chris Forbes // direct ordering between QP and subsequent work, so QP (and its 107119867daedbf52debc77d6568162ee21e071699b80Chris Forbes // semaphore waits) /never/ participate in any completion proof. 107126c87c6a8acda49a6406192a1b634e9bf060bd6fdChris Forbes } 107131344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis 107145b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 107155b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 107165b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10717c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinskistatic bool PreCallValidateCreateSharedSwapchainsKHR(layer_data *dev_data, uint32_t swapchainCount, 10718c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski const VkSwapchainCreateInfoKHR *pCreateInfos, VkSwapchainKHR *pSwapchains, 10719c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski std::vector<SURFACE_STATE *> &surface_state, 10720c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski std::vector<SWAPCHAIN_NODE *> &old_swapchain_state) { 107210342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski if (pCreateInfos) { 10722c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski std::lock_guard<std::mutex> lock(global_lock); 107230342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski for (uint32_t i = 0; i < swapchainCount; i++) { 107249a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis surface_state.push_back(GetSurfaceState(dev_data->instance_data, pCreateInfos[i].surface)); 107259a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis old_swapchain_state.push_back(GetSwapchainNode(dev_data, pCreateInfos[i].oldSwapchain)); 107269ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski std::stringstream func_name; 107279ad55a294cd317a63498d79878e1d5e7d1156c91Mark Lobodzinski func_name << "vkCreateSharedSwapchainsKHR[" << swapchainCount << "]"; 10728bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski if (PreCallValidateCreateSwapchainKHR(dev_data, func_name.str().c_str(), &pCreateInfos[i], surface_state[i], 10729bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski old_swapchain_state[i])) { 10730c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski return true; 107310342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski } 107320342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski } 107330342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski } 10734c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski return false; 10735c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski} 107360342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski 10737c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinskistatic void PostCallRecordCreateSharedSwapchainsKHR(layer_data *dev_data, VkResult result, uint32_t swapchainCount, 10738c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski const VkSwapchainCreateInfoKHR *pCreateInfos, VkSwapchainKHR *pSwapchains, 10739c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski std::vector<SURFACE_STATE *> &surface_state, 10740c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski std::vector<SWAPCHAIN_NODE *> &old_swapchain_state) { 107410342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski if (VK_SUCCESS == result) { 107420342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski for (uint32_t i = 0; i < swapchainCount; i++) { 107430342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski auto swapchain_state = unique_ptr<SWAPCHAIN_NODE>(new SWAPCHAIN_NODE(&pCreateInfos[i], pSwapchains[i])); 107440342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski surface_state[i]->swapchain = swapchain_state.get(); 107450342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski dev_data->device_extensions.swapchainMap[pSwapchains[i]] = std::move(swapchain_state); 107460342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski } 107470342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski } else { 107480342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski for (uint32_t i = 0; i < swapchainCount; i++) { 107490342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski surface_state[i]->swapchain = nullptr; 107500342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski } 107510342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski } 107520342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski // Spec requires that even if CreateSharedSwapchainKHR fails, oldSwapchain behaves as replaced. 107530342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski for (uint32_t i = 0; i < swapchainCount; i++) { 107540342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski if (old_swapchain_state[i]) { 107550342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski old_swapchain_state[i]->replaced = true; 107560342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski } 107570342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski surface_state[i]->old_swapchain = old_swapchain_state[i]; 107580342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski } 10759c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski return; 10760c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski} 10761c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski 10762c6cd632d064579a64e61d8704b411d0e4ace7adaMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateSharedSwapchainsKHR(VkDevice device, uint32_t swapchainCount, 10763c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski const VkSwapchainCreateInfoKHR *pCreateInfos, 10764c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchains) { 1076556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 10766c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski std::vector<SURFACE_STATE *> surface_state; 10767c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski std::vector<SWAPCHAIN_NODE *> old_swapchain_state; 10768c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski 10769c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski if (PreCallValidateCreateSharedSwapchainsKHR(dev_data, swapchainCount, pCreateInfos, pSwapchains, surface_state, 10770c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski old_swapchain_state)) { 10771c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski return VK_ERROR_VALIDATION_FAILED_EXT; 10772c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski } 10773c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski 10774c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski VkResult result = 10775c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski dev_data->dispatch_table.CreateSharedSwapchainsKHR(device, swapchainCount, pCreateInfos, pAllocator, pSwapchains); 10776c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski 10777c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski PostCallRecordCreateSharedSwapchainsKHR(dev_data, result, swapchainCount, pCreateInfos, pSwapchains, surface_state, 10778c6cd632d064579a64e61d8704b411d0e4ace7adaMark Lobodzinski old_swapchain_state); 107790342b03ca27e5dcd692e5161af9e0eddda80240eMark Lobodzinski 10780c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young return result; 10781c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young} 10782c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young 1078389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR VkResult VKAPI_CALL AcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, 1078489d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu VkSemaphore semaphore, VkFence fence, uint32_t *pImageIndex) { 1078556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 107863251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 107871344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis 10788b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::unique_lock<std::mutex> lock(global_lock); 10789449670637ef4214b33018f497cf10daeff9dc85bChris Forbes 10790449670637ef4214b33018f497cf10daeff9dc85bChris Forbes if (fence == VK_NULL_HANDLE && semaphore == VK_NULL_HANDLE) { 107913251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, 107923251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t &>(device), __LINE__, DRAWSTATE_SWAPCHAIN_NO_SYNC_FOR_ACQUIRE, "DS", 107933251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkAcquireNextImageKHR: Semaphore and fence cannot both be VK_NULL_HANDLE. There would be no way " 107943251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "to determine the completion of this operation."); 10795449670637ef4214b33018f497cf10daeff9dc85bChris Forbes } 10796449670637ef4214b33018f497cf10daeff9dc85bChris Forbes 107979a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pSemaphore = GetSemaphoreNode(dev_data, semaphore); 10798f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes if (pSemaphore && pSemaphore->signaled) { 107993251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT, 108003251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<const uint64_t &>(semaphore), __LINE__, VALIDATION_ERROR_01952, "DS", 108013251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkAcquireNextImageKHR: Semaphore must not be currently signaled or in a wait state. %s", 108023251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski validation_error_map[VALIDATION_ERROR_01952]); 108035b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 10804f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes 108059a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto pFence = GetFenceNode(dev_data, fence); 10806f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes if (pFence) { 108073251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= ValidateFenceForSubmit(dev_data, pFence); 108085b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 108094a5614452104c88cb04390dac882dd94ebdcc3deChris Forbes 108109a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto swapchain_data = GetSwapchainNode(dev_data, swapchain); 10811fc9f0448c3cb6ba4fc018fefe761bb43a1884846Chris Forbes 10812fc9f0448c3cb6ba4fc018fefe761bb43a1884846Chris Forbes if (swapchain_data->replaced) { 108133251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 108143251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t &>(swapchain), __LINE__, DRAWSTATE_SWAPCHAIN_REPLACED, "DS", 108153251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkAcquireNextImageKHR: This swapchain has been replaced. The application can still " 108163251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "present any images it has acquired, but cannot acquire any more."); 10817fc9f0448c3cb6ba4fc018fefe761bb43a1884846Chris Forbes } 10818fc9f0448c3cb6ba4fc018fefe761bb43a1884846Chris Forbes 108199a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto physical_device_state = GetPhysicalDeviceState(dev_data->instance_data, dev_data->physical_device); 108204a5614452104c88cb04390dac882dd94ebdcc3deChris Forbes if (physical_device_state->vkGetPhysicalDeviceSurfaceCapabilitiesKHRState != UNCALLED) { 108216569ab421f45f905e69fa7345bda4fe5b87e9045Mark Lobodzinski uint64_t acquired_images = std::count_if(swapchain_data->images.begin(), swapchain_data->images.end(), 108229a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis [=](VkImage image) { return GetImageState(dev_data, image)->acquired; }); 108234a5614452104c88cb04390dac882dd94ebdcc3deChris Forbes if (acquired_images > swapchain_data->images.size() - physical_device_state->surfaceCapabilities.minImageCount) { 108243251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 108256569ab421f45f905e69fa7345bda4fe5b87e9045Mark Lobodzinski log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 108266569ab421f45f905e69fa7345bda4fe5b87e9045Mark Lobodzinski reinterpret_cast<uint64_t const &>(swapchain), __LINE__, DRAWSTATE_SWAPCHAIN_TOO_MANY_IMAGES, "DS", 108276569ab421f45f905e69fa7345bda4fe5b87e9045Mark Lobodzinski "vkAcquireNextImageKHR: Application has already acquired the maximum number of images (0x%" PRIxLEAST64 ")", 108286569ab421f45f905e69fa7345bda4fe5b87e9045Mark Lobodzinski acquired_images); 108294a5614452104c88cb04390dac882dd94ebdcc3deChris Forbes } 108304a5614452104c88cb04390dac882dd94ebdcc3deChris Forbes } 1083175269fc9e5cc9696ddf3dd28ff201c9b2526dc7aThomas Louis 1083275269fc9e5cc9696ddf3dd28ff201c9b2526dc7aThomas Louis if (swapchain_data->images.size() == 0) { 108333251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, 108343251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski reinterpret_cast<uint64_t const &>(swapchain), __LINE__, DRAWSTATE_SWAPCHAIN_IMAGES_NOT_FOUND, "DS", 108353251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkAcquireNextImageKHR: No images found to acquire from. Application probably did not call " 108363251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkGetSwapchainImagesKHR after swapchain creation."); 1083775269fc9e5cc9696ddf3dd28ff201c9b2526dc7aThomas Louis } 1083875269fc9e5cc9696ddf3dd28ff201c9b2526dc7aThomas Louis 10839b9e992386a44404152747d66817a733aa127e281Jeremy Hayes lock.unlock(); 108401344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis 108413251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 10842f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes 108434a0754042cf090e131e9e769d8a3633c228625beChris Forbes VkResult result = dev_data->dispatch_table.AcquireNextImageKHR(device, swapchain, timeout, semaphore, fence, pImageIndex); 10844f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes 10845f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes lock.lock(); 10846f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes if (result == VK_SUCCESS || result == VK_SUBOPTIMAL_KHR) { 10847f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes if (pFence) { 10848f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes pFence->state = FENCE_INFLIGHT; 10849cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski pFence->signaler.first = VK_NULL_HANDLE; // ANI isn't on a queue, so this can't participate in a completion proof. 10850f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes } 10851f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes 10852f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes // A successful call to AcquireNextImageKHR counts as a signal operation on semaphore 10853f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes if (pSemaphore) { 10854f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes pSemaphore->signaled = true; 108559867daedbf52debc77d6568162ee21e071699b80Chris Forbes pSemaphore->signaler.first = VK_NULL_HANDLE; 10856f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes } 10857220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes 10858220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes // Mark the image as acquired. 10859220a9249bd81543e570b3f38c79d9b1e82e0d0dbChris Forbes auto image = swapchain_data->images[*pImageIndex]; 108609a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto image_state = GetImageState(dev_data, image); 108611facd2c91911508b9fb61f54a56269841299f663Tobin Ehlis image_state->acquired = true; 108625b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 10863f91af4dfe0646cf509616910a8ec2d72c423ccdaChris Forbes lock.unlock(); 108641344302fce242e654df2fd518b6371a91b8a5c7dTobin Ehlis 108655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return result; 108665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 108675b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 10868f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL EnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount, 10869f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski VkPhysicalDevice *pPhysicalDevices) { 108703251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 1087156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 10872bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis assert(instance_data); 10873219f00ffed576643641976122fa1db8e5fce5dc1Chris Forbes 10874bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis // For this instance, flag when vkEnumeratePhysicalDevices goes to QUERY_COUNT and then QUERY_DETAILS 10875bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis if (NULL == pPhysicalDevices) { 10876bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis instance_data->vkEnumeratePhysicalDevicesState = QUERY_COUNT; 10877f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski } else { 10878bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis if (UNCALLED == instance_data->vkEnumeratePhysicalDevicesState) { 10879bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis // Flag warning here. You can call this without having queried the count, but it may not be 10880bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis // robust on platforms with multiple physical devices. 108813251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, 108823251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski 0, __LINE__, DEVLIMITS_MISSING_QUERY_COUNT, "DL", 108833251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Call sequence has vkEnumeratePhysicalDevices() w/ non-NULL pPhysicalDevices. You should first " 108843251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "call vkEnumeratePhysicalDevices() w/ NULL pPhysicalDevices to query pPhysicalDeviceCount."); 10885cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } // TODO : Could also flag a warning if re-calling this function in QUERY_DETAILS state 10886bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis else if (instance_data->physical_devices_count != *pPhysicalDeviceCount) { 10887bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis // Having actual count match count from app is not a requirement, so this can be a warning 108883251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, 108893251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_COUNT_MISMATCH, "DL", 108903251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Call to vkEnumeratePhysicalDevices() w/ pPhysicalDeviceCount value %u, but actual count " 108913251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "supported by this instance is %u.", 108923251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski *pPhysicalDeviceCount, instance_data->physical_devices_count); 10893bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis } 10894bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis instance_data->vkEnumeratePhysicalDevicesState = QUERY_DETAILS; 10895f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski } 108963251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (skip) { 10897bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis return VK_ERROR_VALIDATION_FAILED_EXT; 10898bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis } 10899bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis VkResult result = instance_data->dispatch_table.EnumeratePhysicalDevices(instance, pPhysicalDeviceCount, pPhysicalDevices); 10900bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis if (NULL == pPhysicalDevices) { 10901bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis instance_data->physical_devices_count = *pPhysicalDeviceCount; 10902cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } else if (result == VK_SUCCESS) { // Save physical devices 10903bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++) { 10904bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis auto &phys_device_state = instance_data->physical_device_map[pPhysicalDevices[i]]; 10905bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis phys_device_state.phys_device = pPhysicalDevices[i]; 10906bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis // Init actual features for each physical device 10907bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis instance_data->dispatch_table.GetPhysicalDeviceFeatures(pPhysicalDevices[i], &phys_device_state.features); 10908bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis } 10909bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis } 10910bfd47e4db53f595683fbe192d73bbda5c56606a6Tobin Ehlis return result; 10911f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski} 10912f83fcc51d156b056966509bfe4d05c9ccb37ce5dMark Lobodzinski 1091343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis// Common function to handle validation for GetPhysicalDeviceQueueFamilyProperties & 2KHR version 1091443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic bool ValidateCommonGetPhysicalDeviceQueueFamilyProperties(instance_layer_data *instance_data, 1091543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis PHYSICAL_DEVICE_STATE *pd_state, 1091643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis uint32_t *pQueueFamilyPropertyCount, bool qfp_null, 1091743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis const char *count_var_name, const char *caller_name) { 1091843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis bool skip = false; 1091943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis if (qfp_null) { 1092043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis pd_state->vkGetPhysicalDeviceQueueFamilyPropertiesState = QUERY_COUNT; 1092143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } else { 1092243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis // Verify that for each physical device, this function is called first with NULL pQueueFamilyProperties ptr in order to get 1092343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis // count 1092443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis if (UNCALLED == pd_state->vkGetPhysicalDeviceQueueFamilyPropertiesState) { 1092543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, 1092643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_MISSING_QUERY_COUNT, "DL", 1092743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis "Call sequence has %s() w/ non-NULL " 1092843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis "pQueueFamilyProperties. You should first call %s() w/ " 1092943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis "NULL pQueueFamilyProperties to query pCount.", 1093043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis caller_name, caller_name); 1093143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 1093243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis // Then verify that pCount that is passed in on second call matches what was returned 1093343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis if (pd_state->queueFamilyPropertiesCount != *pQueueFamilyPropertyCount) { 1093443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis // TODO: this is not a requirement of the Valid Usage section for vkGetPhysicalDeviceQueueFamilyProperties, so 1093543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis // provide as warning 1093643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, 1093743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_COUNT_MISMATCH, "DL", 1093843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis "Call to %s() w/ %s value %u, but actual count supported by this physicalDevice is %u.", caller_name, 1093943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis count_var_name, *pQueueFamilyPropertyCount, pd_state->queueFamilyPropertiesCount); 1094043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 1094143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis pd_state->vkGetPhysicalDeviceQueueFamilyPropertiesState = QUERY_DETAILS; 1094243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 1094343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis return skip; 1094443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis} 1094543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis 1094643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic bool PreCallValidateGetPhysicalDeviceQueueFamilyProperties(instance_layer_data *instance_data, 1094743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis PHYSICAL_DEVICE_STATE *pd_state, uint32_t *pCount, 1094843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis VkQueueFamilyProperties *pQueueFamilyProperties) { 1094943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis return ValidateCommonGetPhysicalDeviceQueueFamilyProperties(instance_data, pd_state, pCount, 1095043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis (nullptr == pQueueFamilyProperties), "pCount", 1095143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis "vkGetPhysicalDeviceQueueFamilyProperties()"); 1095243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis} 1095343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis 1095443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic bool PreCallValidateGetPhysicalDeviceQueueFamilyProperties2KHR(instance_layer_data *instance_data, 1095543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis PHYSICAL_DEVICE_STATE *pd_state, 1095643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis uint32_t *pQueueFamilyPropertyCount, 1095743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis VkQueueFamilyProperties2KHR *pQueueFamilyProperties) { 1095843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis return ValidateCommonGetPhysicalDeviceQueueFamilyProperties(instance_data, pd_state, pQueueFamilyPropertyCount, 1095943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis (nullptr == pQueueFamilyProperties), "pQueueFamilyPropertyCount", 1096043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis "vkGetPhysicalDeviceQueueFamilyProperties2KHR()"); 1096143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis} 1096243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis 1096343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis// Common function to update state for GetPhysicalDeviceQueueFamilyProperties & 2KHR version 1096443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic void StateUpdateCommonGetPhysicalDeviceQueueFamilyProperties(PHYSICAL_DEVICE_STATE *pd_state, uint32_t count, 1096543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis VkQueueFamilyProperties2KHR *pQueueFamilyProperties) { 1096643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis if (!pQueueFamilyProperties) { 1096743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis pd_state->queueFamilyPropertiesCount = count; 1096843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } else { // Save queue family properties 1096943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis if (pd_state->queue_family_properties.size() < count) pd_state->queue_family_properties.resize(count); 1097043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis for (uint32_t i = 0; i < count; i++) { 1097143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis pd_state->queue_family_properties[i] = pQueueFamilyProperties[i].queueFamilyProperties; 1097243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 1097343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 1097443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis} 1097543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis 1097643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic void PostCallRecordGetPhysicalDeviceQueueFamilyProperties(PHYSICAL_DEVICE_STATE *pd_state, uint32_t count, 1097743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis VkQueueFamilyProperties *pQueueFamilyProperties) { 1097843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis VkQueueFamilyProperties2KHR *pqfp = nullptr; 1097943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis std::vector<VkQueueFamilyProperties2KHR> qfp; 1098043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis qfp.resize(count); 1098143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis if (pQueueFamilyProperties) { 1098243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis for (uint32_t i = 0; i < count; ++i) { 1098343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis qfp[i].sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2_KHR; 1098443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis qfp[i].pNext = nullptr; 1098543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis qfp[i].queueFamilyProperties = pQueueFamilyProperties[i]; 1098643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 1098743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis pqfp = qfp.data(); 1098843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 1098943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis StateUpdateCommonGetPhysicalDeviceQueueFamilyProperties(pd_state, count, pqfp); 1099043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis} 1099143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis 1099243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic void PostCallRecordGetPhysicalDeviceQueueFamilyProperties2KHR(PHYSICAL_DEVICE_STATE *pd_state, uint32_t count, 1099343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis VkQueueFamilyProperties2KHR *pQueueFamilyProperties) { 1099443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis StateUpdateCommonGetPhysicalDeviceQueueFamilyProperties(pd_state, count, pQueueFamilyProperties); 1099543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis} 1099643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis 10997bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, 10998bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkQueueFamilyProperties *pQueueFamilyProperties) { 1099956e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 110009a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto physical_device_state = GetPhysicalDeviceState(instance_data, physicalDevice); 1100143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis assert(physical_device_state); 1100243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis bool skip = 1100343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis PreCallValidateGetPhysicalDeviceQueueFamilyProperties(instance_data, physical_device_state, pCount, pQueueFamilyProperties); 1100443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis if (skip) { 1100543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis return; 1100643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 1100743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis instance_data->dispatch_table.GetPhysicalDeviceQueueFamilyProperties(physicalDevice, pCount, pQueueFamilyProperties); 1100843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis PostCallRecordGetPhysicalDeviceQueueFamilyProperties(physical_device_state, *pCount, pQueueFamilyProperties); 1100943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis} 1101043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis 1101143947a6175e3e942e04d902f4d18928168e2d0dbTobin EhlisVKAPI_ATTR void VKAPI_CALL GetPhysicalDeviceQueueFamilyProperties2KHR(VkPhysicalDevice physicalDevice, 1101243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis uint32_t *pQueueFamilyPropertyCount, 1101343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis VkQueueFamilyProperties2KHR *pQueueFamilyProperties) { 1101456e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 110159a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto physical_device_state = GetPhysicalDeviceState(instance_data, physicalDevice); 1101643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis assert(physical_device_state); 1101743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis bool skip = PreCallValidateGetPhysicalDeviceQueueFamilyProperties2KHR(instance_data, physical_device_state, 1101843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis pQueueFamilyPropertyCount, pQueueFamilyProperties); 1101943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis if (skip) { 1102043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis return; 11021cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski } 1102243947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis instance_data->dispatch_table.GetPhysicalDeviceQueueFamilyProperties2KHR(physicalDevice, pQueueFamilyPropertyCount, 1102343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis pQueueFamilyProperties); 1102443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis PostCallRecordGetPhysicalDeviceQueueFamilyProperties2KHR(physical_device_state, *pQueueFamilyPropertyCount, 1102543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis pQueueFamilyProperties); 11026cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski} 11027cd569b3559a7f8dca06012165480a4e6d7e6c492Mark Lobodzinski 11028bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskitemplate <typename TCreateInfo, typename FPtr> 11029bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic VkResult CreateSurface(VkInstance instance, TCreateInfo const *pCreateInfo, VkAllocationCallbacks const *pAllocator, 11030bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkSurfaceKHR *pSurface, FPtr fptr) { 1103156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 11032747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11033747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes // Call down the call chain: 11034747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes VkResult result = (instance_data->dispatch_table.*fptr)(instance, pCreateInfo, pAllocator, pSurface); 11035747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11036747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (result == VK_SUCCESS) { 11037747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes std::unique_lock<std::mutex> lock(global_lock); 11038747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->surface_map[*pSurface] = SURFACE_STATE(*pSurface); 11039747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes lock.unlock(); 11040747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes } 11041747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11042747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes return result; 11043747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 11044747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11045747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR void VKAPI_CALL DestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks *pAllocator) { 110463251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 1104756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 11048747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes std::unique_lock<std::mutex> lock(global_lock); 110499a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto surface_state = GetSurfaceState(instance_data, surface); 11050747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11051747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (surface_state) { 11052747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes // TODO: track swapchains created from this surface. 11053747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->surface_map.erase(surface); 11054747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes } 11055747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes lock.unlock(); 11056747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 110573251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (!skip) { 11058747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes // Call down the call chain: 11059747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_data->dispatch_table.DestroySurfaceKHR(instance, surface, pAllocator); 11060747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes } 11061747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 11062747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 110636f2ed666809272002a31b3b4f8adf6581cb41819Norbert NopperVKAPI_ATTR VkResult VKAPI_CALL CreateDisplayPlaneSurfaceKHR(VkInstance instance, const VkDisplaySurfaceCreateInfoKHR *pCreateInfo, 110646f2ed666809272002a31b3b4f8adf6581cb41819Norbert Nopper const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) { 110656f2ed666809272002a31b3b4f8adf6581cb41819Norbert Nopper return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateDisplayPlaneSurfaceKHR); 110666f2ed666809272002a31b3b4f8adf6581cb41819Norbert Nopper} 110676f2ed666809272002a31b3b4f8adf6581cb41819Norbert Nopper 11068747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_ANDROID_KHR 11069747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR *pCreateInfo, 11070747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) { 11071747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateAndroidSurfaceKHR); 11072747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 11073cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_ANDROID_KHR 11074747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11075747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_MIR_KHR 11076747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateMirSurfaceKHR(VkInstance instance, const VkMirSurfaceCreateInfoKHR *pCreateInfo, 11077747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) { 11078747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateMirSurfaceKHR); 11079747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 11080cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_MIR_KHR 11081747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11082747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_WAYLAND_KHR 11083747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateWaylandSurfaceKHR(VkInstance instance, const VkWaylandSurfaceCreateInfoKHR *pCreateInfo, 11084747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) { 11085a9c6cc532ce0ef61d48d1419a96aae51b0e4c64aTobin Ehlis return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateWaylandSurfaceKHR); 11086747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 11087cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_WAYLAND_KHR 11088747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11089747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_WIN32_KHR 11090747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateWin32SurfaceKHR(VkInstance instance, const VkWin32SurfaceCreateInfoKHR *pCreateInfo, 11091747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) { 11092747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateWin32SurfaceKHR); 11093747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 11094cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_WIN32_KHR 11095747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11096747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_XCB_KHR 11097747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateXcbSurfaceKHR(VkInstance instance, const VkXcbSurfaceCreateInfoKHR *pCreateInfo, 11098747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) { 11099747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateXcbSurfaceKHR); 11100747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 11101cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_XCB_KHR 11102747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11103747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_XLIB_KHR 11104747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL CreateXlibSurfaceKHR(VkInstance instance, const VkXlibSurfaceCreateInfoKHR *pCreateInfo, 11105bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) { 11106747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes return CreateSurface(instance, pCreateInfo, pAllocator, pSurface, &VkLayerInstanceDispatchTable::CreateXlibSurfaceKHR); 11107747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 11108cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_XLIB_KHR 11109747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 1111040921785005eb449ec7c18229f0d84c879708b8aChris ForbesVKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, 1111140921785005eb449ec7c18229f0d84c879708b8aChris Forbes VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) { 1111256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis auto instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 1111340921785005eb449ec7c18229f0d84c879708b8aChris Forbes 1111440921785005eb449ec7c18229f0d84c879708b8aChris Forbes std::unique_lock<std::mutex> lock(global_lock); 111159a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto physical_device_state = GetPhysicalDeviceState(instance_data, physicalDevice); 1111640921785005eb449ec7c18229f0d84c879708b8aChris Forbes lock.unlock(); 1111740921785005eb449ec7c18229f0d84c879708b8aChris Forbes 11118bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto result = 11119bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski instance_data->dispatch_table.GetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, pSurfaceCapabilities); 1112040921785005eb449ec7c18229f0d84c879708b8aChris Forbes 1112140921785005eb449ec7c18229f0d84c879708b8aChris Forbes if (result == VK_SUCCESS) { 1112240921785005eb449ec7c18229f0d84c879708b8aChris Forbes physical_device_state->vkGetPhysicalDeviceSurfaceCapabilitiesKHRState = QUERY_DETAILS; 1112340921785005eb449ec7c18229f0d84c879708b8aChris Forbes physical_device_state->surfaceCapabilities = *pSurfaceCapabilities; 1112440921785005eb449ec7c18229f0d84c879708b8aChris Forbes } 1112540921785005eb449ec7c18229f0d84c879708b8aChris Forbes 1112640921785005eb449ec7c18229f0d84c879708b8aChris Forbes return result; 1112740921785005eb449ec7c18229f0d84c879708b8aChris Forbes} 1112840921785005eb449ec7c18229f0d84c879708b8aChris Forbes 11129418a8711f3301f3027a900bb45daaf0892f4e644Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, 11130418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes VkSurfaceKHR surface, VkBool32 *pSupported) { 1113156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis auto instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 11132418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes std::unique_lock<std::mutex> lock(global_lock); 111339a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto surface_state = GetSurfaceState(instance_data, surface); 11134418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes lock.unlock(); 11135418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes 11136bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto result = 11137bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski instance_data->dispatch_table.GetPhysicalDeviceSurfaceSupportKHR(physicalDevice, queueFamilyIndex, surface, pSupported); 11138418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes 11139418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes if (result == VK_SUCCESS) { 111406569ab421f45f905e69fa7345bda4fe5b87e9045Mark Lobodzinski surface_state->gpu_queue_support[{physicalDevice, queueFamilyIndex}] = (*pSupported != 0); 11141418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes } 11142418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes 11143418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes return result; 11144418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes} 11145418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes 111469e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, 111479e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes uint32_t *pPresentModeCount, 111489e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes VkPresentModeKHR *pPresentModes) { 111493251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 1115056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis auto instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 111519e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes std::unique_lock<std::mutex> lock(global_lock); 111529e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes // TODO: this isn't quite right. available modes may differ by surface AND physical device. 111539a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto physical_device_state = GetPhysicalDeviceState(instance_data, physicalDevice); 11154bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto &call_state = physical_device_state->vkGetPhysicalDeviceSurfacePresentModesKHRState; 111559e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes 111569e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (pPresentModes) { 111579e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes // Compare the preliminary value of *pPresentModeCount with the value this time: 11158bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto prev_mode_count = (uint32_t)physical_device_state->present_modes.size(); 111599e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes switch (call_state) { 11160cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case UNCALLED: 111613251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg( 11162bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 11163cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski reinterpret_cast<uint64_t>(physicalDevice), __LINE__, DEVLIMITS_MUST_QUERY_COUNT, "DL", 11164cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkGetPhysicalDeviceSurfacePresentModesKHR() called with non-NULL pPresentModeCount; but no prior positive " 11165cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "value has been seen for pPresentModeCount."); 11166cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 11167cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 11168cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // both query count and query details 11169cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (*pPresentModeCount != prev_mode_count) { 111703251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, 111713251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, reinterpret_cast<uint64_t>(physicalDevice), 111723251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski __LINE__, DEVLIMITS_COUNT_MISMATCH, "DL", 111733251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "vkGetPhysicalDeviceSurfacePresentModesKHR() called with *pPresentModeCount (%u) that " 111743251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "differs from the value " 111753251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "(%u) that was returned when pPresentModes was NULL.", 111763251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski *pPresentModeCount, prev_mode_count); 11177cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 11178cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 111799e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 111809e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 111819e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes lock.unlock(); 111829e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes 111833251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 111849e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes 11185bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto result = instance_data->dispatch_table.GetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, pPresentModeCount, 11186bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski pPresentModes); 111879e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes 111889e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (result == VK_SUCCESS || result == VK_INCOMPLETE) { 111899e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes lock.lock(); 111909e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes 111919e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (*pPresentModeCount) { 11192cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (call_state < QUERY_COUNT) call_state = QUERY_COUNT; 111939e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (*pPresentModeCount > physical_device_state->present_modes.size()) 111949e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes physical_device_state->present_modes.resize(*pPresentModeCount); 111959e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 111969e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes if (pPresentModes) { 11197cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (call_state < QUERY_DETAILS) call_state = QUERY_DETAILS; 111989e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes for (uint32_t i = 0; i < *pPresentModeCount; i++) { 111999e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes physical_device_state->present_modes[i] = pPresentModes[i]; 112009e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 112019e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 112025faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 112035faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes 112045faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes return result; 112055faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes} 112065faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes 112075faa662f6859b01c72d79027abde363d5f10dcd7Chris ForbesVKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, 112085faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes uint32_t *pSurfaceFormatCount, 112095faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes VkSurfaceFormatKHR *pSurfaceFormats) { 112103251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 1121156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis auto instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 112125faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes std::unique_lock<std::mutex> lock(global_lock); 112139a9a0db2a973034d4286b6d4c62a46beb7641791Tobin Ehlis auto physical_device_state = GetPhysicalDeviceState(instance_data, physicalDevice); 11214bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto &call_state = physical_device_state->vkGetPhysicalDeviceSurfaceFormatsKHRState; 112155faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes 112165faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (pSurfaceFormats) { 11217bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski auto prev_format_count = (uint32_t)physical_device_state->surface_formats.size(); 112185faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes 112195faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes switch (call_state) { 11220cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski case UNCALLED: 11221cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // Since we haven't recorded a preliminary value of *pSurfaceFormatCount, that likely means that the application 11222cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // didn't 11223cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski // previously call this function with a NULL value of pSurfaceFormats: 112243251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg( 11225bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 11226cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski reinterpret_cast<uint64_t>(physicalDevice), __LINE__, DEVLIMITS_MUST_QUERY_COUNT, "DL", 11227cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkGetPhysicalDeviceSurfaceFormatsKHR() called with non-NULL pSurfaceFormatCount; but no prior positive " 11228cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "value has been seen for pSurfaceFormats."); 11229cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 11230cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski default: 11231cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (prev_format_count != *pSurfaceFormatCount) { 112323251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg( 11233cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, 11234cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, reinterpret_cast<uint64_t>(physicalDevice), __LINE__, 11235cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski DEVLIMITS_COUNT_MISMATCH, "DL", 11236cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "vkGetPhysicalDeviceSurfaceFormatsKHR() called with non-NULL pSurfaceFormatCount, and with pSurfaceFormats " 11237cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "set " 11238cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "to " 11239cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski "a value (%u) that is greater than the value (%u) that was returned when pSurfaceFormatCount was NULL.", 11240cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski *pSurfaceFormatCount, prev_format_count); 11241cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski } 11242cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski break; 112439e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 112449e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes } 112455faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes lock.unlock(); 112465faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes 112473251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (skip) return VK_ERROR_VALIDATION_FAILED_EXT; 112489e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes 112495faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes // Call down the call chain: 112505faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes auto result = instance_data->dispatch_table.GetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, pSurfaceFormatCount, 112515faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes pSurfaceFormats); 112525faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes 112535faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (result == VK_SUCCESS || result == VK_INCOMPLETE) { 112545faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes lock.lock(); 112555faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes 112565faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (*pSurfaceFormatCount) { 11257cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (call_state < QUERY_COUNT) call_state = QUERY_COUNT; 112585faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (*pSurfaceFormatCount > physical_device_state->surface_formats.size()) 112595faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes physical_device_state->surface_formats.resize(*pSurfaceFormatCount); 112605faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 112615faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes if (pSurfaceFormats) { 11262cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (call_state < QUERY_DETAILS) call_state = QUERY_DETAILS; 112635faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes for (uint32_t i = 0; i < *pSurfaceFormatCount; i++) { 112645faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes physical_device_state->surface_formats[i] = pSurfaceFormats[i]; 112655faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 112665faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 112675faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes } 112689e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes return result; 112699e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes} 112709e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes 11271bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateDebugReportCallbackEXT(VkInstance instance, 11272bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkDebugReportCallbackCreateInfoEXT *pCreateInfo, 11273bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, 11274bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDebugReportCallbackEXT *pMsgCallback) { 1127556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 112769172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes VkResult res = instance_data->dispatch_table.CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback); 112775b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis if (VK_SUCCESS == res) { 11278b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 112798860b85a52096f9f9b28616bc37feed505497a54Chris Forbes res = layer_create_msg_callback(instance_data->report_data, false, pCreateInfo, pAllocator, pMsgCallback); 112805b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis } 112815b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis return res; 112825b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 112835b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 11284bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT msgCallback, 1128589d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu const VkAllocationCallbacks *pAllocator) { 1128656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 112879172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes instance_data->dispatch_table.DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator); 11288b9e992386a44404152747d66817a733aa127e281Jeremy Hayes std::lock_guard<std::mutex> lock(global_lock); 112898860b85a52096f9f9b28616bc37feed505497a54Chris Forbes layer_destroy_msg_callback(instance_data->report_data, msgCallback, pAllocator); 112905b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 112915b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 11292bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, 11293bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDebugReportObjectTypeEXT objType, uint64_t object, size_t location, 11294bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski int32_t msgCode, const char *pLayerPrefix, const char *pMsg) { 1129556e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 112969172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes instance_data->dispatch_table.DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg); 112975b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 112985b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 11299bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) { 11300a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu return util_GetLayerProperties(1, &global_layer, pCount, pProperties); 11301a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu} 11302a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu 11303bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, 11304bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkLayerProperties *pProperties) { 11305a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu return util_GetLayerProperties(1, &global_layer, pCount, pProperties); 11306a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu} 11307a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu 11308bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, 11309bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkExtensionProperties *pProperties) { 11310a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) 11311a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties); 11312a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu 11313a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu return VK_ERROR_LAYER_NOT_PRESENT; 11314a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu} 11315a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu 11316bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName, 11317bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski uint32_t *pCount, VkExtensionProperties *pProperties) { 11318cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) return util_GetExtensionProperties(0, NULL, pCount, pProperties); 11319a8f4a23b1e9c068717eda47cc583a93f447c77e3Chia-I Wu 11320a8f4a23b1e9c068717eda47cc583a93f447c77e3Chia-I Wu assert(physicalDevice); 11321a8f4a23b1e9c068717eda47cc583a93f447c77e3Chia-I Wu 1132256e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(physicalDevice), instance_layer_data_map); 113239172b640a0ae6a92f24ad0609d92b2c228cde89cChris Forbes return instance_data->dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties); 1132408939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu} 1132508939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu 11326582b6ed09649188d55ed3b6237352caf9f3384a9Mike WeiblenVKAPI_ATTR VkResult VKAPI_CALL EnumeratePhysicalDeviceGroupsKHX( 11327582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen VkInstance instance, uint32_t *pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupPropertiesKHX *pPhysicalDeviceGroupProperties) { 113283251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski bool skip = false; 11329582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 11330582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen 11331582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen if (instance_data) { 11332582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen // For this instance, flag when EnumeratePhysicalDeviceGroupsKHX goes to QUERY_COUNT and then QUERY_DETAILS. 11333582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen if (NULL == pPhysicalDeviceGroupProperties) { 11334582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen instance_data->vkEnumeratePhysicalDeviceGroupsState = QUERY_COUNT; 11335582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen } else { 11336582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen if (UNCALLED == instance_data->vkEnumeratePhysicalDeviceGroupsState) { 11337582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen // Flag warning here. You can call this without having queried the count, but it may not be 11338582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen // robust on platforms with multiple physical devices. 113393251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, 113403251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, 0, __LINE__, DEVLIMITS_MISSING_QUERY_COUNT, "DL", 113413251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Call sequence has vkEnumeratePhysicalDeviceGroupsKHX() w/ non-NULL " 113423251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "pPhysicalDeviceGroupProperties. You should first " 113433251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "call vkEnumeratePhysicalDeviceGroupsKHX() w/ NULL pPhysicalDeviceGroupProperties to query " 113443251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "pPhysicalDeviceGroupCount."); 11345582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen } // TODO : Could also flag a warning if re-calling this function in QUERY_DETAILS state 11346582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen else if (instance_data->physical_device_groups_count != *pPhysicalDeviceGroupCount) { 11347582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen // Having actual count match count from app is not a requirement, so this can be a warning 113483251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski skip |= 11349582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen log_msg(instance_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, 113503251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_COUNT_MISMATCH, "DL", 113513251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "Call to vkEnumeratePhysicalDeviceGroupsKHX() w/ pPhysicalDeviceGroupCount value %u, but actual count " 113523251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski "supported by this instance is %u.", 113533251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski *pPhysicalDeviceGroupCount, instance_data->physical_device_groups_count); 11354582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen } 11355582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen instance_data->vkEnumeratePhysicalDeviceGroupsState = QUERY_DETAILS; 11356582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen } 113573251dd855490066e66a663dece5afee8ca0b95cdMark Lobodzinski if (skip) { 11358582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen return VK_ERROR_VALIDATION_FAILED_EXT; 11359582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen } 11360582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen VkResult result = instance_data->dispatch_table.EnumeratePhysicalDeviceGroupsKHX(instance, pPhysicalDeviceGroupCount, 11361582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen pPhysicalDeviceGroupProperties); 11362582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen if (NULL == pPhysicalDeviceGroupProperties) { 11363582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen instance_data->physical_device_groups_count = *pPhysicalDeviceGroupCount; 11364582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen } else if (result == VK_SUCCESS) { // Save physical devices 11365582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen for (uint32_t i = 0; i < *pPhysicalDeviceGroupCount; i++) { 11366582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen for (uint32_t j = 0; j < pPhysicalDeviceGroupProperties[i].physicalDeviceCount; j++) { 11367582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen VkPhysicalDevice cur_phys_dev = pPhysicalDeviceGroupProperties[i].physicalDevices[j]; 11368582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen auto &phys_device_state = instance_data->physical_device_map[cur_phys_dev]; 11369582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen phys_device_state.phys_device = cur_phys_dev; 11370582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen // Init actual features for each physical device 11371582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen instance_data->dispatch_table.GetPhysicalDeviceFeatures(cur_phys_dev, &phys_device_state.features); 11372582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen } 11373582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen } 11374582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen } 11375582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen return result; 11376582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen } else { 11377582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen log_msg(instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, 0, __LINE__, 11378582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen DEVLIMITS_INVALID_INSTANCE, "DL", 11379582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen "Invalid instance (0x%" PRIxLEAST64 ") passed into vkEnumeratePhysicalDeviceGroupsKHX().", (uint64_t)instance); 11380582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen } 11381582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen return VK_ERROR_VALIDATION_FAILED_EXT; 11382582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen} 11383582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen 113846246f8feba03ddc787c31b3daa6a50d4ef01024fMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL CreateDescriptorUpdateTemplateKHR(VkDevice device, 113856246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski const VkDescriptorUpdateTemplateCreateInfoKHR *pCreateInfo, 113866246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski const VkAllocationCallbacks *pAllocator, 113876246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski VkDescriptorUpdateTemplateKHR *pDescriptorUpdateTemplate) { 113886246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 11389a538cd4fff983b172362b0bba58f984124481a1cMark Lobodzinski VkResult result = 11390a538cd4fff983b172362b0bba58f984124481a1cMark Lobodzinski dev_data->dispatch_table.CreateDescriptorUpdateTemplateKHR(device, pCreateInfo, pAllocator, pDescriptorUpdateTemplate); 113916246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski if (VK_SUCCESS == result) { 113926246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski std::lock_guard<std::mutex> lock(global_lock); 113936246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski // Shadow template createInfo for later updates 11394a538cd4fff983b172362b0bba58f984124481a1cMark Lobodzinski safe_VkDescriptorUpdateTemplateCreateInfoKHR *local_create_info = 11395a538cd4fff983b172362b0bba58f984124481a1cMark Lobodzinski new safe_VkDescriptorUpdateTemplateCreateInfoKHR(pCreateInfo); 113966246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski std::unique_ptr<TEMPLATE_STATE> template_state(new TEMPLATE_STATE(*pDescriptorUpdateTemplate, local_create_info)); 113976246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski dev_data->desc_template_map[*pDescriptorUpdateTemplate] = std::move(template_state); 113986246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski } 113996246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski return result; 114006246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski} 114016246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski 114026246f8feba03ddc787c31b3daa6a50d4ef01024fMark LobodzinskiVKAPI_ATTR void VKAPI_CALL DestroyDescriptorUpdateTemplateKHR(VkDevice device, 114036246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate, 114046246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski const VkAllocationCallbacks *pAllocator) { 114056246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 114066246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski std::unique_lock<std::mutex> lock(global_lock); 114076246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski dev_data->desc_template_map.erase(descriptorUpdateTemplate); 114086246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski lock.unlock(); 114096246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski dev_data->dispatch_table.DestroyDescriptorUpdateTemplateKHR(device, descriptorUpdateTemplate, pAllocator); 114106246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski} 114116246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski 1141225f3712aed1cebdcb7c92eb25c5f1cc6e5986ac4Mark Lobodzinski// PostCallRecord* handles recording state updates following call down chain to UpdateDescriptorSetsWithTemplate() 1141325f3712aed1cebdcb7c92eb25c5f1cc6e5986ac4Mark Lobodzinskistatic void PostCallRecordUpdateDescriptorSetWithTemplateKHR(layer_data *device_data, VkDescriptorSet descriptorSet, 1141425f3712aed1cebdcb7c92eb25c5f1cc6e5986ac4Mark Lobodzinski VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate, 1141525f3712aed1cebdcb7c92eb25c5f1cc6e5986ac4Mark Lobodzinski const void *pData) { 1141667fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski auto const template_map_entry = device_data->desc_template_map.find(descriptorUpdateTemplate); 1141767fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski if (template_map_entry == device_data->desc_template_map.end()) { 1141867fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski assert(0); 1141967fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski } 1142067fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski 1142125f3712aed1cebdcb7c92eb25c5f1cc6e5986ac4Mark Lobodzinski cvdescriptorset::PerformUpdateDescriptorSetsWithTemplateKHR(device_data, descriptorSet, template_map_entry->second, pData); 1142267fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski} 1142367fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski 114246246f8feba03ddc787c31b3daa6a50d4ef01024fMark LobodzinskiVKAPI_ATTR void VKAPI_CALL UpdateDescriptorSetWithTemplateKHR(VkDevice device, VkDescriptorSet descriptorSet, 114256246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate, 114266246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski const void *pData) { 1142767fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski layer_data *device_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 1142867fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski device_data->dispatch_table.UpdateDescriptorSetWithTemplateKHR(device, descriptorSet, descriptorUpdateTemplate, pData); 1142967fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski 1143067fe2a610e6fc19f5bf11df4b663cef1f6c4e9caMark Lobodzinski PostCallRecordUpdateDescriptorSetWithTemplateKHR(device_data, descriptorSet, descriptorUpdateTemplate, pData); 114316246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski} 114326246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski 114336246f8feba03ddc787c31b3daa6a50d4ef01024fMark LobodzinskiVKAPI_ATTR void VKAPI_CALL CmdPushDescriptorSetWithTemplateKHR(VkCommandBuffer commandBuffer, 114346246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski VkDescriptorUpdateTemplateKHR descriptorUpdateTemplate, 114356246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski VkPipelineLayout layout, uint32_t set, const void *pData) { 114366246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map); 114376246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski dev_data->dispatch_table.CmdPushDescriptorSetWithTemplateKHR(commandBuffer, descriptorUpdateTemplate, layout, set, pData); 114386246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski} 114396246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski 11440bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic PFN_vkVoidFunction intercept_core_instance_command(const char *name); 114417ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu 11442bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic PFN_vkVoidFunction intercept_core_device_command(const char *name); 1144380be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu 114446246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinskistatic PFN_vkVoidFunction intercept_device_extension_command(const char *name, VkDevice device); 114456246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski 11446bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic PFN_vkVoidFunction intercept_khr_swapchain_command(const char *name, VkDevice dev); 1144709a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu 11448bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic PFN_vkVoidFunction intercept_khr_surface_command(const char *name, VkInstance instance); 11449747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11450582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblenstatic PFN_vkVoidFunction 11451582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblenintercept_extension_instance_commands(const char *name, VkInstance instance); 11452b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 1145389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice dev, const char *funcName) { 1145480be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu assert(dev); 114555b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 114566246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski PFN_vkVoidFunction proc = intercept_core_device_command(funcName); 114576246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski if (!proc) proc = intercept_device_extension_command(funcName, dev); 114586246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski if (!proc) proc = intercept_khr_swapchain_command(funcName, dev); 11459cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (proc) return proc; 1146009a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu 1146156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(dev), layer_data_map); 114624a0754042cf090e131e9e769d8a3633c228625beChris Forbes auto &table = dev_data->dispatch_table; 11463cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!table.GetDeviceProcAddr) return nullptr; 114644a0754042cf090e131e9e769d8a3633c228625beChris Forbes return table.GetDeviceProcAddr(dev, funcName); 114655b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 114665b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1146789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I WuVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) { 114687ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu PFN_vkVoidFunction proc = intercept_core_instance_command(funcName); 11469cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!proc) proc = intercept_core_device_command(funcName); 11470cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!proc) proc = intercept_khr_swapchain_command(funcName, VK_NULL_HANDLE); 11471cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!proc) proc = intercept_khr_surface_command(funcName, instance); 11472cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (proc) return proc; 114735b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 114747ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu assert(instance); 114755b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 1147656e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 114778860b85a52096f9f9b28616bc37feed505497a54Chris Forbes proc = debug_report_get_instance_proc_addr(instance_data->report_data, funcName); 11478cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (proc) return proc; 114795b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis 11480b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young proc = intercept_extension_instance_commands(funcName, instance); 11481cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (proc) return proc; 11482b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 114834a0754042cf090e131e9e769d8a3633c228625beChris Forbes auto &table = instance_data->dispatch_table; 11484cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!table.GetInstanceProcAddr) return nullptr; 114854a0754042cf090e131e9e769d8a3633c228625beChris Forbes return table.GetInstanceProcAddr(instance, funcName); 114865b5e7bcfe47d9ed90d0d5edbbe11edf7214a7784Tobin Ehlis} 1148708939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu 11488b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark YoungVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetPhysicalDeviceProcAddr(VkInstance instance, const char *funcName) { 11489b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young assert(instance); 11490b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 1149156e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 11492b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 11493b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young auto &table = instance_data->dispatch_table; 11494cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!table.GetPhysicalDeviceProcAddr) return nullptr; 11495b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young return table.GetPhysicalDeviceProcAddr(instance, funcName); 11496b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young} 11497b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 11498bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic PFN_vkVoidFunction intercept_core_instance_command(const char *name) { 114997ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu static const struct { 115007ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu const char *name; 115017ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu PFN_vkVoidFunction proc; 115027ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu } core_instance_commands[] = { 11503bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkGetInstanceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr)}, 11504bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vk_layerGetPhysicalDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceProcAddr)}, 11505bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkGetDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr)}, 11506bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkCreateInstance", reinterpret_cast<PFN_vkVoidFunction>(CreateInstance)}, 11507bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkCreateDevice", reinterpret_cast<PFN_vkVoidFunction>(CreateDevice)}, 11508bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkEnumeratePhysicalDevices", reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDevices)}, 11509bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkGetPhysicalDeviceQueueFamilyProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceQueueFamilyProperties)}, 11510bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance)}, 11511bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkEnumerateInstanceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceLayerProperties)}, 11512bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkEnumerateDeviceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceLayerProperties)}, 11513bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkEnumerateInstanceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceExtensionProperties)}, 11514bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkEnumerateDeviceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceExtensionProperties)}, 115157ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu }; 115167ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu 115177ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu for (size_t i = 0; i < ARRAY_SIZE(core_instance_commands); i++) { 11518cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!strcmp(core_instance_commands[i].name, name)) return core_instance_commands[i].proc; 115197ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu } 115207ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu 115217ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu return nullptr; 115227ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu} 115237ed76a2d9a619f963e7a1afb13e9913fbc09dc63Chia-I Wu 11524bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic PFN_vkVoidFunction intercept_core_device_command(const char *name) { 1152580be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu static const struct { 1152680be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu const char *name; 1152780be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu PFN_vkVoidFunction proc; 1152880be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu } core_device_commands[] = { 11529593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkGetDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr)}, 11530593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkQueueSubmit", reinterpret_cast<PFN_vkVoidFunction>(QueueSubmit)}, 11531593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkWaitForFences", reinterpret_cast<PFN_vkVoidFunction>(WaitForFences)}, 11532593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkGetFenceStatus", reinterpret_cast<PFN_vkVoidFunction>(GetFenceStatus)}, 11533593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkQueueWaitIdle", reinterpret_cast<PFN_vkVoidFunction>(QueueWaitIdle)}, 11534593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDeviceWaitIdle", reinterpret_cast<PFN_vkVoidFunction>(DeviceWaitIdle)}, 11535593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkGetDeviceQueue", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceQueue)}, 11536593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance)}, 11537593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyDevice", reinterpret_cast<PFN_vkVoidFunction>(DestroyDevice)}, 11538593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyFence", reinterpret_cast<PFN_vkVoidFunction>(DestroyFence)}, 11539593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkResetFences", reinterpret_cast<PFN_vkVoidFunction>(ResetFences)}, 11540593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroySemaphore", reinterpret_cast<PFN_vkVoidFunction>(DestroySemaphore)}, 11541593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyEvent", reinterpret_cast<PFN_vkVoidFunction>(DestroyEvent)}, 11542593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyQueryPool", reinterpret_cast<PFN_vkVoidFunction>(DestroyQueryPool)}, 11543593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyBuffer", reinterpret_cast<PFN_vkVoidFunction>(DestroyBuffer)}, 11544593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyBufferView", reinterpret_cast<PFN_vkVoidFunction>(DestroyBufferView)}, 11545593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyImage", reinterpret_cast<PFN_vkVoidFunction>(DestroyImage)}, 11546593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyImageView", reinterpret_cast<PFN_vkVoidFunction>(DestroyImageView)}, 11547593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyShaderModule", reinterpret_cast<PFN_vkVoidFunction>(DestroyShaderModule)}, 11548593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyPipeline", reinterpret_cast<PFN_vkVoidFunction>(DestroyPipeline)}, 11549593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyPipelineLayout", reinterpret_cast<PFN_vkVoidFunction>(DestroyPipelineLayout)}, 11550593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroySampler", reinterpret_cast<PFN_vkVoidFunction>(DestroySampler)}, 11551593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyDescriptorSetLayout", reinterpret_cast<PFN_vkVoidFunction>(DestroyDescriptorSetLayout)}, 11552593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(DestroyDescriptorPool)}, 11553593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyFramebuffer", reinterpret_cast<PFN_vkVoidFunction>(DestroyFramebuffer)}, 11554593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyRenderPass", reinterpret_cast<PFN_vkVoidFunction>(DestroyRenderPass)}, 11555593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateBuffer", reinterpret_cast<PFN_vkVoidFunction>(CreateBuffer)}, 11556593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateBufferView", reinterpret_cast<PFN_vkVoidFunction>(CreateBufferView)}, 11557593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateImage", reinterpret_cast<PFN_vkVoidFunction>(CreateImage)}, 11558593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateImageView", reinterpret_cast<PFN_vkVoidFunction>(CreateImageView)}, 11559593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateFence", reinterpret_cast<PFN_vkVoidFunction>(CreateFence)}, 11560593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreatePipelineCache", reinterpret_cast<PFN_vkVoidFunction>(CreatePipelineCache)}, 11561593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyPipelineCache", reinterpret_cast<PFN_vkVoidFunction>(DestroyPipelineCache)}, 11562593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkGetPipelineCacheData", reinterpret_cast<PFN_vkVoidFunction>(GetPipelineCacheData)}, 11563593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkMergePipelineCaches", reinterpret_cast<PFN_vkVoidFunction>(MergePipelineCaches)}, 11564593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateGraphicsPipelines", reinterpret_cast<PFN_vkVoidFunction>(CreateGraphicsPipelines)}, 11565593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateComputePipelines", reinterpret_cast<PFN_vkVoidFunction>(CreateComputePipelines)}, 11566593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateSampler", reinterpret_cast<PFN_vkVoidFunction>(CreateSampler)}, 11567593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateDescriptorSetLayout", reinterpret_cast<PFN_vkVoidFunction>(CreateDescriptorSetLayout)}, 11568593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreatePipelineLayout", reinterpret_cast<PFN_vkVoidFunction>(CreatePipelineLayout)}, 11569593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(CreateDescriptorPool)}, 11570593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkResetDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(ResetDescriptorPool)}, 11571593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkAllocateDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(AllocateDescriptorSets)}, 11572593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkFreeDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(FreeDescriptorSets)}, 11573593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkUpdateDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(UpdateDescriptorSets)}, 11574593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateCommandPool", reinterpret_cast<PFN_vkVoidFunction>(CreateCommandPool)}, 11575593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkDestroyCommandPool", reinterpret_cast<PFN_vkVoidFunction>(DestroyCommandPool)}, 11576593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkResetCommandPool", reinterpret_cast<PFN_vkVoidFunction>(ResetCommandPool)}, 11577593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateQueryPool", reinterpret_cast<PFN_vkVoidFunction>(CreateQueryPool)}, 11578593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkAllocateCommandBuffers", reinterpret_cast<PFN_vkVoidFunction>(AllocateCommandBuffers)}, 11579593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkFreeCommandBuffers", reinterpret_cast<PFN_vkVoidFunction>(FreeCommandBuffers)}, 11580593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkBeginCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(BeginCommandBuffer)}, 11581593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkEndCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(EndCommandBuffer)}, 11582593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkResetCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(ResetCommandBuffer)}, 11583593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdBindPipeline", reinterpret_cast<PFN_vkVoidFunction>(CmdBindPipeline)}, 11584593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdSetViewport", reinterpret_cast<PFN_vkVoidFunction>(CmdSetViewport)}, 11585593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdSetScissor", reinterpret_cast<PFN_vkVoidFunction>(CmdSetScissor)}, 11586593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdSetLineWidth", reinterpret_cast<PFN_vkVoidFunction>(CmdSetLineWidth)}, 11587593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdSetDepthBias", reinterpret_cast<PFN_vkVoidFunction>(CmdSetDepthBias)}, 11588593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdSetBlendConstants", reinterpret_cast<PFN_vkVoidFunction>(CmdSetBlendConstants)}, 11589593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdSetDepthBounds", reinterpret_cast<PFN_vkVoidFunction>(CmdSetDepthBounds)}, 11590593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdSetStencilCompareMask", reinterpret_cast<PFN_vkVoidFunction>(CmdSetStencilCompareMask)}, 11591593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdSetStencilWriteMask", reinterpret_cast<PFN_vkVoidFunction>(CmdSetStencilWriteMask)}, 11592593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdSetStencilReference", reinterpret_cast<PFN_vkVoidFunction>(CmdSetStencilReference)}, 11593593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdBindDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(CmdBindDescriptorSets)}, 11594593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdBindVertexBuffers", reinterpret_cast<PFN_vkVoidFunction>(CmdBindVertexBuffers)}, 11595593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdBindIndexBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdBindIndexBuffer)}, 11596593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdDraw", reinterpret_cast<PFN_vkVoidFunction>(CmdDraw)}, 11597593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdDrawIndexed", reinterpret_cast<PFN_vkVoidFunction>(CmdDrawIndexed)}, 11598593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdDrawIndirect", reinterpret_cast<PFN_vkVoidFunction>(CmdDrawIndirect)}, 11599593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdDrawIndexedIndirect", reinterpret_cast<PFN_vkVoidFunction>(CmdDrawIndexedIndirect)}, 11600593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdDispatch", reinterpret_cast<PFN_vkVoidFunction>(CmdDispatch)}, 11601593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdDispatchIndirect", reinterpret_cast<PFN_vkVoidFunction>(CmdDispatchIndirect)}, 11602593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdCopyBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyBuffer)}, 11603593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdCopyImage", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyImage)}, 11604593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdBlitImage", reinterpret_cast<PFN_vkVoidFunction>(CmdBlitImage)}, 11605593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdCopyBufferToImage", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyBufferToImage)}, 11606593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdCopyImageToBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyImageToBuffer)}, 11607593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdUpdateBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdUpdateBuffer)}, 11608593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdFillBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdFillBuffer)}, 11609593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdClearColorImage", reinterpret_cast<PFN_vkVoidFunction>(CmdClearColorImage)}, 11610593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdClearDepthStencilImage", reinterpret_cast<PFN_vkVoidFunction>(CmdClearDepthStencilImage)}, 11611593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdClearAttachments", reinterpret_cast<PFN_vkVoidFunction>(CmdClearAttachments)}, 11612593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdResolveImage", reinterpret_cast<PFN_vkVoidFunction>(CmdResolveImage)}, 11613b06379a335598a3d8c53c694e875dda19eeab612Mark Lobodzinski {"vkGetImageSubresourceLayout", reinterpret_cast<PFN_vkVoidFunction>(GetImageSubresourceLayout) }, 11614593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdSetEvent", reinterpret_cast<PFN_vkVoidFunction>(CmdSetEvent)}, 11615593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdResetEvent", reinterpret_cast<PFN_vkVoidFunction>(CmdResetEvent)}, 11616593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdWaitEvents", reinterpret_cast<PFN_vkVoidFunction>(CmdWaitEvents)}, 11617593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdPipelineBarrier", reinterpret_cast<PFN_vkVoidFunction>(CmdPipelineBarrier)}, 11618593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdBeginQuery", reinterpret_cast<PFN_vkVoidFunction>(CmdBeginQuery)}, 11619593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdEndQuery", reinterpret_cast<PFN_vkVoidFunction>(CmdEndQuery)}, 11620593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdResetQueryPool", reinterpret_cast<PFN_vkVoidFunction>(CmdResetQueryPool)}, 11621593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdCopyQueryPoolResults", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyQueryPoolResults)}, 11622593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdPushConstants", reinterpret_cast<PFN_vkVoidFunction>(CmdPushConstants)}, 11623593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdWriteTimestamp", reinterpret_cast<PFN_vkVoidFunction>(CmdWriteTimestamp)}, 11624593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateFramebuffer", reinterpret_cast<PFN_vkVoidFunction>(CreateFramebuffer)}, 11625593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateShaderModule", reinterpret_cast<PFN_vkVoidFunction>(CreateShaderModule)}, 11626593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateRenderPass", reinterpret_cast<PFN_vkVoidFunction>(CreateRenderPass)}, 11627593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdBeginRenderPass", reinterpret_cast<PFN_vkVoidFunction>(CmdBeginRenderPass)}, 11628593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdNextSubpass", reinterpret_cast<PFN_vkVoidFunction>(CmdNextSubpass)}, 11629593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdEndRenderPass", reinterpret_cast<PFN_vkVoidFunction>(CmdEndRenderPass)}, 11630593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCmdExecuteCommands", reinterpret_cast<PFN_vkVoidFunction>(CmdExecuteCommands)}, 11631593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkSetEvent", reinterpret_cast<PFN_vkVoidFunction>(SetEvent)}, 11632593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkMapMemory", reinterpret_cast<PFN_vkVoidFunction>(MapMemory)}, 11633593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkUnmapMemory", reinterpret_cast<PFN_vkVoidFunction>(UnmapMemory)}, 11634593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkFlushMappedMemoryRanges", reinterpret_cast<PFN_vkVoidFunction>(FlushMappedMemoryRanges)}, 11635593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkInvalidateMappedMemoryRanges", reinterpret_cast<PFN_vkVoidFunction>(InvalidateMappedMemoryRanges)}, 11636593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkAllocateMemory", reinterpret_cast<PFN_vkVoidFunction>(AllocateMemory)}, 11637593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkFreeMemory", reinterpret_cast<PFN_vkVoidFunction>(FreeMemory)}, 11638593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkBindBufferMemory", reinterpret_cast<PFN_vkVoidFunction>(BindBufferMemory)}, 11639593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkGetBufferMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(GetBufferMemoryRequirements)}, 11640593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkGetImageMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(GetImageMemoryRequirements)}, 11641593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkGetQueryPoolResults", reinterpret_cast<PFN_vkVoidFunction>(GetQueryPoolResults)}, 11642593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkBindImageMemory", reinterpret_cast<PFN_vkVoidFunction>(BindImageMemory)}, 11643593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkQueueBindSparse", reinterpret_cast<PFN_vkVoidFunction>(QueueBindSparse)}, 11644593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateSemaphore", reinterpret_cast<PFN_vkVoidFunction>(CreateSemaphore)}, 11645593c857d8db57cf9ae2c590b75e22dadd51bd3d4Tobin Ehlis {"vkCreateEvent", reinterpret_cast<PFN_vkVoidFunction>(CreateEvent)}, 1164680be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu }; 1164780be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu 1164880be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu for (size_t i = 0; i < ARRAY_SIZE(core_device_commands); i++) { 11649cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!strcmp(core_device_commands[i].name, name)) return core_device_commands[i].proc; 116506246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski } 116516246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski 116526246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski return nullptr; 116536246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski} 116546246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski 116556246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinskistatic PFN_vkVoidFunction intercept_device_extension_command(const char *name, VkDevice device) { 116566246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski layer_data *device_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map); 116576246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski 116586246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski const struct { 116596246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski const char *name; 116606246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski PFN_vkVoidFunction proc; 116616246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski bool enabled; 116626246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski } device_extension_commands[] = { 116636246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski {"vkCreateDescriptorUpdateTemplateKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateDescriptorUpdateTemplateKHR), 116646246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski device_data->device_extensions.khr_descriptor_update_template_enabled}, 116656246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski {"vkDestroyDescriptorUpdateTemplateKHR", reinterpret_cast<PFN_vkVoidFunction>(DestroyDescriptorUpdateTemplateKHR), 116666246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski device_data->device_extensions.khr_descriptor_update_template_enabled}, 116676246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski {"vkUpdateDescriptorSetWithTemplateKHR", reinterpret_cast<PFN_vkVoidFunction>(UpdateDescriptorSetWithTemplateKHR), 116686246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski device_data->device_extensions.khr_descriptor_update_template_enabled}, 116696246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski {"vkCmdPushDescriptorSetWithTemplateKHR", reinterpret_cast<PFN_vkVoidFunction>(CmdPushDescriptorSetWithTemplateKHR), 116706246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski device_data->device_extensions.khr_descriptor_update_template_enabled}, 116716246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski }; 116726246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski 116736246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski if (!device_data || !device_data->device_extensions.khr_descriptor_update_template_enabled) return nullptr; 116746246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski 116756246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski for (size_t i = 0; i < ARRAY_SIZE(device_extension_commands); i++) { 116766246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski if (!strcmp(device_extension_commands[i].name, name) && device_extension_commands[i].enabled) 116776246f8feba03ddc787c31b3daa6a50d4ef01024fMark Lobodzinski return device_extension_commands[i].proc; 1167880be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu } 1167980be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu 1168080be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu return nullptr; 1168180be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu} 1168280be5ddd2f71eae65d790fe63d1e5b1e1f4daa42Chia-I Wu 11683bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic PFN_vkVoidFunction intercept_khr_swapchain_command(const char *name, VkDevice dev) { 1168409a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu static const struct { 1168509a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu const char *name; 1168609a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu PFN_vkVoidFunction proc; 1168709a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu } khr_swapchain_commands[] = { 11688bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkCreateSwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateSwapchainKHR)}, 11689bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkDestroySwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(DestroySwapchainKHR)}, 11690bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkGetSwapchainImagesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetSwapchainImagesKHR)}, 11691bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkAcquireNextImageKHR", reinterpret_cast<PFN_vkVoidFunction>(AcquireNextImageKHR)}, 11692bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkQueuePresentKHR", reinterpret_cast<PFN_vkVoidFunction>(QueuePresentKHR)}, 1169309a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu }; 11694c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young layer_data *dev_data = nullptr; 1169509a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu 116963f6f8132355ebdae2736b31fc20de2ac60a70310Chia-I Wu if (dev) { 1169756e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis dev_data = GetLayerDataPtr(get_dispatch_key(dev), layer_data_map); 11698599899dabe438a8ea144c0add628d3f5afe54dd0Chris Forbes if (!dev_data->device_extensions.khr_swapchain_enabled) return nullptr; 116993f6f8132355ebdae2736b31fc20de2ac60a70310Chia-I Wu } 1170009a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu 1170109a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu for (size_t i = 0; i < ARRAY_SIZE(khr_swapchain_commands); i++) { 11702cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!strcmp(khr_swapchain_commands[i].name, name)) return khr_swapchain_commands[i].proc; 1170309a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu } 1170409a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu 11705c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young if (dev_data) { 11706599899dabe438a8ea144c0add628d3f5afe54dd0Chris Forbes if (!dev_data->device_extensions.khr_display_swapchain_enabled) return nullptr; 11707c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young } 11708c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young 11709cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (!strcmp("vkCreateSharedSwapchainsKHR", name)) return reinterpret_cast<PFN_vkVoidFunction>(CreateSharedSwapchainsKHR); 11710c827a5880dc3fabfc7d1a58bb62798649cab1181Mark Young 1171109a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu return nullptr; 11712747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes} 11713747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11714bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinskistatic PFN_vkVoidFunction intercept_khr_surface_command(const char *name, VkInstance instance) { 11715747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes static const struct { 11716747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes const char *name; 11717747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes PFN_vkVoidFunction proc; 11718747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes bool instance_layer_data::*enable; 11719747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes } khr_surface_commands[] = { 11720747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_ANDROID_KHR 11721747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes {"vkCreateAndroidSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateAndroidSurfaceKHR), 11722bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::androidSurfaceExtensionEnabled}, 11723cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_ANDROID_KHR 11724747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_MIR_KHR 11725747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes {"vkCreateMirSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateMirSurfaceKHR), 11726bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::mirSurfaceExtensionEnabled}, 11727cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_MIR_KHR 11728747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_WAYLAND_KHR 11729747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes {"vkCreateWaylandSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateWaylandSurfaceKHR), 11730bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::waylandSurfaceExtensionEnabled}, 11731cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_WAYLAND_KHR 11732747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_WIN32_KHR 11733747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes {"vkCreateWin32SurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateWin32SurfaceKHR), 11734bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::win32SurfaceExtensionEnabled}, 11735cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_WIN32_KHR 11736747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_XCB_KHR 11737747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes {"vkCreateXcbSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateXcbSurfaceKHR), 11738bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::xcbSurfaceExtensionEnabled}, 11739cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_XCB_KHR 11740747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes#ifdef VK_USE_PLATFORM_XLIB_KHR 11741747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes {"vkCreateXlibSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateXlibSurfaceKHR), 11742bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::xlibSurfaceExtensionEnabled}, 11743cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski#endif // VK_USE_PLATFORM_XLIB_KHR 11744bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski {"vkCreateDisplayPlaneSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateDisplayPlaneSurfaceKHR), 11745bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::displayExtensionEnabled}, 11746747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes {"vkDestroySurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(DestroySurfaceKHR), 11747bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::surfaceExtensionEnabled}, 1174840921785005eb449ec7c18229f0d84c879708b8aChris Forbes {"vkGetPhysicalDeviceSurfaceCapabilitiesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceCapabilitiesKHR), 11749bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::surfaceExtensionEnabled}, 11750418a8711f3301f3027a900bb45daaf0892f4e644Chris Forbes {"vkGetPhysicalDeviceSurfaceSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceSupportKHR), 11751bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::surfaceExtensionEnabled}, 117529e8e286e0ca0c7cd911c3e7ba3ddd1aceb29cbe9Chris Forbes {"vkGetPhysicalDeviceSurfacePresentModesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfacePresentModesKHR), 11753bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::surfaceExtensionEnabled}, 117545faa662f6859b01c72d79027abde363d5f10dcd7Chris Forbes {"vkGetPhysicalDeviceSurfaceFormatsKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceFormatsKHR), 11755bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski &instance_layer_data::surfaceExtensionEnabled}, 11756747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes }; 11757747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11758747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes instance_layer_data *instance_data = nullptr; 11759747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (instance) { 1176056e14f5c1c3c1cc8e3137bee5c3093d238763a42Tobin Ehlis instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map); 11761747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes } 11762747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11763747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes for (size_t i = 0; i < ARRAY_SIZE(khr_surface_commands); i++) { 11764747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes if (!strcmp(khr_surface_commands[i].name, name)) { 11765cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski if (instance_data && !(instance_data->*(khr_surface_commands[i].enable))) return nullptr; 11766747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes return khr_surface_commands[i].proc; 11767747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes } 11768747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes } 11769747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes 11770747ce6dd32eafd93da3dc12a6ffd670e746ae453Chris Forbes return nullptr; 1177109a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu} 1177209a2f8128f58f032b73d29fab5afd789626562c3Chia-I Wu 1177343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlisstatic PFN_vkVoidFunction intercept_extension_instance_commands(const char *name, VkInstance instance) { 1177443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis static const struct { 1177543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis const char *name; 1177643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis PFN_vkVoidFunction proc; 1177743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis bool instance_layer_data::*enable; 1177843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } instance_extension_commands[] = { 1177943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis {"vkGetPhysicalDeviceQueueFamilyProperties2KHR", 1178043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceQueueFamilyProperties2KHR)}, 11781582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen {"vkEnumeratePhysicalDeviceGroupsKHX", 11782582b6ed09649188d55ed3b6237352caf9f3384a9Mike Weiblen reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDeviceGroupsKHX)}, 1178343947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis }; 1178443947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis 1178543947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis for (size_t i = 0; i < ARRAY_SIZE(instance_extension_commands); i++) { 1178643947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis if (!strcmp(instance_extension_commands[i].name, name)) { 1178743947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis return instance_extension_commands[i].proc; 1178843947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 1178943947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis } 1179043947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis return nullptr; 1179143947a6175e3e942e04d902f4d18928168e2d0dbTobin Ehlis} 11792b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 11793cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski} // namespace core_validation 11794d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu 11795d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu// vk_layer_logging.h expects these to be defined 11796d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu 11797bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugReportCallbackEXT(VkInstance instance, 11798bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkDebugReportCallbackCreateInfoEXT *pCreateInfo, 11799bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator, 11800bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDebugReportCallbackEXT *pMsgCallback) { 1180189d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu return core_validation::CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback); 11802d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu} 11803d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu 11804bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT msgCallback, 11805bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const VkAllocationCallbacks *pAllocator) { 1180689d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu core_validation::DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator); 11807d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu} 11808d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu 11809bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVKAPI_ATTR void VKAPI_CALL vkDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, 11810bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkDebugReportObjectTypeEXT objType, uint64_t object, size_t location, 11811bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski int32_t msgCode, const char *pLayerPrefix, const char *pMsg) { 1181289d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu core_validation::DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg); 11813d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu} 11814d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu 11815a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu// loader-layer interface v0, just wrappers since there is only a layer 11816d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu 11817bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, 11818bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkExtensionProperties *pProperties) { 11819a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu return core_validation::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties); 1182008939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu} 1182108939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu 11822bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount, 11823bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkLayerProperties *pProperties) { 11824a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu return core_validation::EnumerateInstanceLayerProperties(pCount, pProperties); 1182508939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu} 1182608939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu 11827bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, 11828bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski VkLayerProperties *pProperties) { 11829a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu // the layer command handles VK_NULL_HANDLE just fine internally 11830a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu assert(physicalDevice == VK_NULL_HANDLE); 11831a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu return core_validation::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties); 11832d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu} 11833d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu 11834d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I WuVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, 11835d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu const char *pLayerName, uint32_t *pCount, 11836d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu VkExtensionProperties *pProperties) { 11837a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu // the layer command handles VK_NULL_HANDLE just fine internally 11838a4e71cd8b4e77502943dd894ed95426a25dffbd5Chia-I Wu assert(physicalDevice == VK_NULL_HANDLE); 11839a8f4a23b1e9c068717eda47cc583a93f447c77e3Chia-I Wu return core_validation::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties); 11840d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu} 11841d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu 11842d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I WuVK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) { 1184389d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu return core_validation::GetDeviceProcAddr(dev, funcName); 11844d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu} 11845d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I Wu 11846d16a2fd05d0b6bd20c7274560c88e37e4b3adefcChia-I WuVK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) { 1184789d6bb8ab0ab38202ecfb3d6e21f60c884cc62e5Chia-I Wu return core_validation::GetInstanceProcAddr(instance, funcName); 1184808939232d080c94fc7b4c5ad348644928beb1519Chia-I Wu} 11849b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 11850bc9caa57c5583dfdf05198e78b78a7cb361da16cMark LobodzinskiVK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance, 11851bc9caa57c5583dfdf05198e78b78a7cb361da16cMark Lobodzinski const char *funcName) { 11852b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young return core_validation::GetPhysicalDeviceProcAddr(instance, funcName); 11853b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young} 11854b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 11855b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark YoungVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface *pVersionStruct) { 11856b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young assert(pVersionStruct != NULL); 11857b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young assert(pVersionStruct->sType == LAYER_NEGOTIATE_INTERFACE_STRUCT); 11858b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 11859b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young // Fill in the function pointers if our version is at least capable of having the structure contain them. 11860b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young if (pVersionStruct->loaderLayerInterfaceVersion >= 2) { 11861b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young pVersionStruct->pfnGetInstanceProcAddr = vkGetInstanceProcAddr; 11862b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young pVersionStruct->pfnGetDeviceProcAddr = vkGetDeviceProcAddr; 11863b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young pVersionStruct->pfnGetPhysicalDeviceProcAddr = vk_layerGetPhysicalDeviceProcAddr; 11864b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young } 11865b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 11866b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young if (pVersionStruct->loaderLayerInterfaceVersion < CURRENT_LOADER_LAYER_INTERFACE_VERSION) { 11867b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young core_validation::loader_layer_if_version = pVersionStruct->loaderLayerInterfaceVersion; 11868b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young } else if (pVersionStruct->loaderLayerInterfaceVersion > CURRENT_LOADER_LAYER_INTERFACE_VERSION) { 11869b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young pVersionStruct->loaderLayerInterfaceVersion = CURRENT_LOADER_LAYER_INTERFACE_VERSION; 11870b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young } 11871b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young 11872b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young return VK_SUCCESS; 11873b5f087aec8b42faee128c5c3dd1cb11b662d85aaMark Young} 11874